//+------------------------------------------------------------------+ //| S5_Direcao1_v4_2.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 "DESENV_v2" #property description "HFT MARKET MAKING BASED ON OXFORD'S STUDIES. MINI INDICE." //INDICE //+===================================================================================================================================================================================+ //| 0 - SESSAO DE CABECALHO / ADMISSAO //+===================================================================================================================================================================================+ //+------------------------------------------------------------------+ //| 0.1 - IMPORTACOES | //+------------------------------------------------------------------+ #include "MarketBook.mqh" #include "S0_Admissao1_v4_2.mqh" //SLOTS_i,q = -Φ*k*q^2 , i=q //SLOTS_i,q = λc/e , i=q-1 //SLOTS_i,q = λv/e , i=q+1 //SLOTS_i,q = 0 , default //+===================================================================================================================================================================================+ //| 5 - SESSAO DE PRECOS / DIRECAO //+===================================================================================================================================================================================+ //+------------------------------------------------------------------+ //| 5.1 - FUNCAO QUE VERIFICA O PRECO NAQUELE INSTANTE | //+------------------------------------------------------------------+ int CalculaPrecoOrdem(operacao &Operacao, fluido &Fluidos, slot &Slots[], MqlTick &ArrayTick[], MqlBookInfo &ArrayBook[]) { //Calcula os spreads if(Slots[0].ponta == 0) { Fluidos.precoMedioC = CalculaSpreadOrdemC(Operacao, Fluidos, Slots, ArrayTick, ArrayBook); } else Fluidos.precoMedioV = CalculaSpreadOrdemV(Operacao, Fluidos, Slots, ArrayTick, ArrayBook); return 0; } //+------------------------------------------------------------------+ //| 5.1 - FUNCAO QUE VERIFICA O PRECO NAQUELE INSTANTE | //+------------------------------------------------------------------+ int CalculaPrecoPosicao(operacao &Operacao, fluido &Fluidos, slot &Slots[], MqlTick &ArrayTick[], MqlBookInfo &ArrayBook[]) { double sAlvoRet = 0.0; double sStopRet = 0.0; //Calcula os spreads if(Slots[0].ponta == 0) { Fluidos.precoMedioC = CalculaSpreadPosicaoC(Operacao, Fluidos, Slots, ArrayTick, ArrayBook, sAlvoRet, sStopRet); } else Fluidos.precoMedioV = CalculaSpreadPosicaoV(Operacao, Fluidos, Slots, ArrayTick, ArrayBook, sAlvoRet, sStopRet); return 0; } //+------------------------------------------------------------------+ //| 5.2 - FUNCAO QUE CALCULA SPREAD BUY | //+------------------------------------------------------------------+ double CalculaSpreadOrdemC(operacao &Operacao, fluido &Fluidos, slot &SlotsC[], MqlTick &ArrayTick[], MqlBookInfo &ArrayBook[]) { double spread = 0.0; double spreadEnvio = 0.0; double spreadAlvo = 0.0; if(Operacao.chaveBook == true) Fluidos.KC = CalculaKC(Fluidos, ArrayBook); if(Operacao.chaveBook == true) Fluidos.KV = CalculaKV(Fluidos, ArrayBook); if(Operacao.chaveLambda == true) Fluidos.lambdaC = CalculaLambdaCompra(ArrayTick, Fluidos.T); if(Operacao.chaveLambda == true) Fluidos.lambdaV = CalculaLambdaVenda(ArrayTick, Fluidos.T); if((Operacao.chaveBook == true) || (Operacao.chaveBook == true)) { Fluidos.eC = CalculaEpsilon(Fluidos.lambdaC, Fluidos.KV); Fluidos.eV = CalculaEpsilon(Fluidos.lambdaV, Fluidos.KC); } double spreadMin = Fluidos.tickMin/2; int n = 10; double HC_q = CalculaHC(Fluidos, Fluidos.q, n); double HC_qmais1 = CalculaHCmais1(Fluidos, Fluidos.q+1, n); double HV_q = CalculaHV(Fluidos, Fluidos.q, n); double HV_qmenos1 = CalculaHVmenos1(Fluidos, Fluidos.q-1, n); double deltaHC = HC_q - HC_qmais1; double deltaHV = HV_q - HV_qmenos1; Fluidos.a = CalculaAlpha(Fluidos, Operacao); double spreadAlpha = MathRound(Fluidos.a*500/Fluidos.tickMin)*Fluidos.tickMin; if(spreadAlpha > -15) { Fluidos.lC = 1; } else { //SE LC FOR 0, NÃO MANDE ORDEM DE COMPRA Fluidos.lC = 0; return spread; } double spreadBaseEnvio = MathRound(((1/Fluidos.KC) - Fluidos.a + Fluidos.eV/10 + deltaHC)*500/Fluidos.tickMin) * Fluidos.tickMin; double spreadBaseAlvo = MathRound(((1/Fluidos.KV) + Fluidos.a + Fluidos.eC/10 + deltaHV)*500/Fluidos.tickMin) * Fluidos.tickMin; double spreadDesvio = MathRound(Fluidos.sigmaHFT / Fluidos.tickMin) * Fluidos.tickMin; double spreadStop = MathRound(Fluidos.sigmaHFT / Fluidos.tickMin) * Fluidos.tickMin * 5; //double nivel = MathRound(log(Fluidos.iSlot+1) * 100 / Fluidos.tickMin) / 100 * Fluidos.tickMin; double nivel = Fluidos.iSlot + 1; //SET SPREAD ENVIO if(spreadBaseEnvio < 0) spreadBaseEnvio = 0; spreadEnvio = spreadMin + ((spreadBaseEnvio + spreadDesvio)/2 * nivel); spreadAlvo = 2*spreadMin + (spreadBaseAlvo + spreadDesvio)/2; //SET PRECO ENVIO SlotsC[Fluidos.iSlot].precoEnvio = Fluidos.midPrice - spreadEnvio; if(MathMod(SlotsC[Fluidos.iSlot].precoEnvio, Fluidos.tickMin) != 0) { SlotsC[Fluidos.iSlot].precoEnvio = SlotsC[Fluidos.iSlot].precoEnvio - MathMod(SlotsC[Fluidos.iSlot].precoEnvio, Fluidos.tickMin); } //SET PRECO ALVO SlotsC[Fluidos.iSlot].precoAlvo = SlotsC[Fluidos.iSlot].precoEnvio + spreadAlvo; if(MathMod(SlotsC[Fluidos.iSlot].precoAlvo, Fluidos.tickMin) != 0) { SlotsC[Fluidos.iSlot].precoAlvo = SlotsC[Fluidos.iSlot].precoAlvo - MathMod(SlotsC[Fluidos.iSlot].precoAlvo, Fluidos.tickMin); } //SET PRECO STOP SlotsC[Fluidos.iSlot].precoStop = SlotsC[Fluidos.iSlot].precoEnvio - spreadStop; if(MathMod(SlotsC[Fluidos.iSlot].precoStop, Fluidos.tickMin) != 0) { SlotsC[Fluidos.iSlot].precoStop = SlotsC[Fluidos.iSlot].precoStop - MathMod(SlotsC[Fluidos.iSlot].precoStop, Fluidos.tickMin); } // Print("HC_q: ", HC_q, " | HV_q: ", HV_q, " | HC_qmais1: ", HC_qmais1, " | HV_qmenos1: ", HV_qmenos1, " | deltaHC: ", deltaHC, " | deltaHV: ", deltaHV); // Print("MidPrice: ", Fluidos.midPrice," | SpreadEnvioC: ", spreadEnvio, " | spreadAlvo: ", spreadAlvo, " | spreadBase: ", spreadBase, " | spreadDesvio: ", spreadDesvio, " | nivel: ", nivel, " | alpha: ", spreadAlpha); //SET TEMPO EXPIRA ORDEM if(Operacao.chaveTempoOrdemAuto == true) { if(nivel == 1) { //Depth double d = spreadEnvio/Fluidos.tickMin; Fluidos.T = 60 * MathRound((Fluidos.KC * d) / pow(Fluidos.lambdaV, 2)); } } // Print("HC_q: ", HC_q, " HC_qmais1: ", HC_qmais1, " diferenca: ", diferenca); // Print("PrecoEnvio: ", SlotsC[Fluidos.iSlot].precoEnvio, " PrecoAlvo: ", SlotsC[Fluidos.iSlot].precoAlvo, " PrecoStop: ", SlotsC[Fluidos.iSlot].precoStop); return spread; } //+------------------------------------------------------------------+ //| 5.3 - FUNCAO QUE CALCULA SPREAD SELL | //+------------------------------------------------------------------+ double CalculaSpreadOrdemV(operacao &Operacao, fluido &Fluidos, slot &SlotsV[], MqlTick &ArrayTick[], MqlBookInfo &ArrayBook[]) { double spread = 0.0; double spreadEnvio = 0.0; double spreadAlvo = 0.0; if(Operacao.chaveBook == true) Fluidos.KC = CalculaKC(Fluidos, ArrayBook); if(Operacao.chaveBook == true) Fluidos.KV = CalculaKV(Fluidos, ArrayBook); if(Operacao.chaveLambda == true) Fluidos.lambdaC = CalculaLambdaCompra(ArrayTick, Fluidos.T); if(Operacao.chaveLambda == true) Fluidos.lambdaV = CalculaLambdaVenda(ArrayTick, Fluidos.T); if((Operacao.chaveBook == true) || (Operacao.chaveBook == true)) { Fluidos.eC = CalculaEpsilon(Fluidos.lambdaC, Fluidos.KV); Fluidos.eV = CalculaEpsilon(Fluidos.lambdaV, Fluidos.KC); } double spreadMin = Fluidos.tickMin/2; Fluidos.eC = spreadMin; Fluidos.eV = spreadMin; int n = 10; double HC_q = CalculaHC(Fluidos, Fluidos.q, n); double HC_qmais1 = CalculaHCmais1(Fluidos, Fluidos.q+1, n); double HV_q = CalculaHV(Fluidos, Fluidos.q, n); double HV_qmenos1 = CalculaHVmenos1(Fluidos, Fluidos.q-1, n); double deltaHC = HC_q - HC_qmais1; double deltaHV = HV_q - HV_qmenos1; Fluidos.a = CalculaAlpha(Fluidos, Operacao); double spreadAlpha = MathRound(Fluidos.a*500/Fluidos.tickMin)*Fluidos.tickMin; if(spreadAlpha < 15) Fluidos.lV = 1; else { Fluidos.lV = 0; return spread; } double spreadBaseEnvio = MathRound(((1/Fluidos.KV) + Fluidos.a + Fluidos.eC/10 + deltaHV)*500/Fluidos.tickMin) * Fluidos.tickMin; double spreadBaseAlvo = MathRound(((1/Fluidos.KC) - Fluidos.a + Fluidos.eV/10 + deltaHC)*500/Fluidos.tickMin) * Fluidos.tickMin; double spreadDesvio = MathRound(Fluidos.sigmaHFT / Fluidos.tickMin) * Fluidos.tickMin; double spreadStop = MathRound(Fluidos.sigmaHFT / Fluidos.tickMin) * Fluidos.tickMin * 5; //double nivel = MathRound(log(Fluidos.iSlot+1) * 100 / Fluidos.tickMin) / 100 * Fluidos.tickMin; double nivel = Fluidos.iSlot + 1; //SET SPREAD ENVIO if(spreadBaseEnvio < 0) spreadBaseEnvio = 0; spreadEnvio = spreadMin + ((spreadBaseEnvio + spreadDesvio)/2 * nivel); spreadAlvo = 2*spreadMin + (spreadBaseAlvo + spreadDesvio)/2; //SET PRECO ENVIO SlotsV[Fluidos.iSlot].precoEnvio = Fluidos.midPrice + spreadEnvio; if(MathMod(SlotsV[Fluidos.iSlot].precoEnvio, Fluidos.tickMin) != 0) { SlotsV[Fluidos.iSlot].precoEnvio = SlotsV[Fluidos.iSlot].precoEnvio + (Fluidos.tickMin - MathMod(SlotsV[Fluidos.iSlot].precoEnvio, Fluidos.tickMin)); } //SET PRECO ALVO SlotsV[Fluidos.iSlot].precoAlvo = SlotsV[Fluidos.iSlot].precoEnvio - spreadAlvo; if(MathMod(SlotsV[Fluidos.iSlot].precoAlvo, Fluidos.tickMin) != 0) { SlotsV[Fluidos.iSlot].precoAlvo = SlotsV[Fluidos.iSlot].precoAlvo + (Fluidos.tickMin - MathMod(SlotsV[Fluidos.iSlot].precoAlvo, Fluidos.tickMin)); } //SET PRECO STOP SlotsV[Fluidos.iSlot].precoStop = SlotsV[Fluidos.iSlot].precoEnvio + spreadStop; if(MathMod(SlotsV[Fluidos.iSlot].precoStop, Fluidos.tickMin) != 0) { SlotsV[Fluidos.iSlot].precoStop = SlotsV[Fluidos.iSlot].precoStop + (Fluidos.tickMin - MathMod(SlotsV[Fluidos.iSlot].precoStop, Fluidos.tickMin)); } // Print("MidPrice: ", Fluidos.midPrice," | SpreadEnvioV: ", spreadEnvio, " | spreadAlvo: ", spreadAlvo, " | spreadBase: ", spreadBase, " | spreadDesvio: ", spreadDesvio, " | nivel: ", nivel, " | alpha: ", spreadAlpha); //SET TEMPO EXPIRA ORDEM if(Operacao.chaveTempoOrdemAuto == true) { if(nivel == 1) { //Depth double d = spreadEnvio/Fluidos.tickMin; Fluidos.T = 60 * MathRound((Fluidos.KV * d) / pow(Fluidos.lambdaC, 2)); } } // Print("HV_q: ", HV_q, " HV_qmenos1: ", HV_qmenos1, " diferenca: ", diferenca); // Print("PrecoEnvio: ", SlotsV[Fluidos.iSlot].precoEnvio, " PrecoAlvo: ", SlotsV[Fluidos.iSlot].precoAlvo, " PrecoStop: ", SlotsV[Fluidos.iSlot].precoStop); return spread; } //+------------------------------------------------------------------+ //| 5.2 - FUNCAO QUE CALCULA SPREAD BUY | //+------------------------------------------------------------------+ double CalculaSpreadPosicaoC(operacao &Operacao, fluido &Fluidos, slot &SlotsC[], MqlTick &ArrayTick[], MqlBookInfo &ArrayBook[], double &spreadAlvoRet, double &spreadStopRet) { /* double spread = 0.0; if(Operacao.chaveBook == true) Fluidos.KV = CalculaKV(Fluidos, ArrayBook); if(Operacao.chaveLambda == true) Fluidos.lambdaC = CalculaLambdaCompra(ArrayTick, Fluidos.T); double HC_q = CalculaHC(Fluidos, Fluidos.q); double HC_qmais1 = CalculaHC(Fluidos, Fluidos.q+1); double deltaH = HC_q - HC_qmais1; if(deltaH < 0) deltaH = 0.0; double spreadMin = Fluidos.tickMin/2; double spreadBase = MathRound( 100 * Fluidos.tickMin * ( (Fluidos.lambdaC/Fluidos.KV) + deltaH ) / Fluidos.tickMin ) * Fluidos.tickMin; double spreadAlvo = spreadMin + spreadBase; double spreadStop = MathRound( Fluidos.sigmaHFT / Fluidos.tickMin ) * Fluidos.tickMin * 5; */ //NOVO SPREAD double spread = 0.0; double spreadAlvo = 0.0; TimeToStruct(TimeCurrent(), Operacao.horarioMQL_atual); int atual = Operacao.horarioMQL_atual.hour * 60 + Operacao.horarioMQL_atual.min; if(Operacao.chaveBook == true) Fluidos.KV = CalculaKV(Fluidos, ArrayBook); if(Operacao.chaveLambda == true) Fluidos.lambdaC = CalculaLambdaCompra(ArrayTick, Fluidos.T); double spreadMin = Fluidos.tickMin/2; Fluidos.eC = spreadMin; Fluidos.eV = spreadMin; int n = 5; double HV_q = CalculaHV(Fluidos, Fluidos.q, n); double HV_qmenos1 = CalculaHV(Fluidos, Fluidos.q-1, n); double deltaH = HV_q - HV_qmenos1; Fluidos.a = CalculaAlpha(Fluidos, Operacao); double spreadAlpha = MathRound(Fluidos.a*500/Fluidos.tickMin)*Fluidos.tickMin; double spreadBase = MathRound(((1/Fluidos.KV) - Fluidos.a + Fluidos.eC/10 + deltaH)*500/Fluidos.tickMin) * Fluidos.tickMin; double spreadDesvio = MathRound(Fluidos.sigmaHFT / Fluidos.tickMin) * Fluidos.tickMin; double spreadStop = MathRound(Fluidos.sigmaHFT / Fluidos.tickMin) * Fluidos.tickMin * 5; if(spreadBase < 0) spreadBase = 0; spreadAlvo = 2*spreadMin + spreadBase + spreadAlpha; if(spreadAlvo < 0) spreadAlvo = Fluidos.tickMin; spreadAlvoRet = spreadAlvo; spreadStopRet = spreadStop; return spread; } //+------------------------------------------------------------------+ //| 5.3 - FUNCAO QUE CALCULA SPREAD SELL | //+------------------------------------------------------------------+ double CalculaSpreadPosicaoV(operacao &Operacao, fluido &Fluidos, slot &SlotsV[], MqlTick &ArrayTick[], MqlBookInfo &ArrayBook[], double &spreadAlvoRet, double &spreadStopRet) { /* double spread = 0.0; if(Operacao.chaveBook == true) Fluidos.KC = CalculaKC(Fluidos, ArrayBook); if(Operacao.chaveLambda == true) Fluidos.lambdaV = CalculaLambdaVenda(ArrayTick, Fluidos.T); double HV_q = CalculaHV(Fluidos, Fluidos.q); double HV_qmenos1 = CalculaHV(Fluidos, Fluidos.q-1); double deltaH = HV_q - HV_qmenos1; if(deltaH < 0) deltaH = 0.0; double spreadMin = Fluidos.tickMin/2; double spreadBase = MathRound( 100 * Fluidos.tickMin * ( (Fluidos.lambdaV/Fluidos.KC) + deltaH ) / Fluidos.tickMin ) * Fluidos.tickMin; double spreadAlvo = spreadMin + spreadBase; double spreadStop = MathRound( Fluidos.sigmaHFT / Fluidos.tickMin ) * Fluidos.tickMin * 5; */ //NOVO SPREAD double spread = 0.0; double spreadAlvo = 0.0; TimeToStruct(TimeCurrent(), Operacao.horarioMQL_atual); int atual = Operacao.horarioMQL_atual.hour * 60 + Operacao.horarioMQL_atual.min; if(Operacao.chaveBook == true) Fluidos.KC = CalculaKC(Fluidos, ArrayBook); if(Operacao.chaveLambda == true) Fluidos.lambdaV = CalculaLambdaVenda(ArrayTick, Fluidos.T); double spreadMin = Fluidos.tickMin/2; Fluidos.eC = spreadMin; Fluidos.eV = spreadMin; int n = 5; double HC_q = CalculaHC(Fluidos, Fluidos.q, n); double HC_qmais1 = CalculaHC(Fluidos, Fluidos.q+1, n); double deltaH = HC_q - HC_qmais1; Fluidos.a = CalculaAlpha(Fluidos, Operacao); double spreadAlpha = MathRound(Fluidos.a*500/Fluidos.tickMin)*Fluidos.tickMin; double spreadBase = MathRound(((1/Fluidos.KC) - Fluidos.a + Fluidos.eV/10 + deltaH)*500/Fluidos.tickMin) * Fluidos.tickMin; double spreadDesvio = MathRound(Fluidos.sigmaHFT / Fluidos.tickMin) * Fluidos.tickMin; double spreadStop = MathRound(Fluidos.sigmaHFT / Fluidos.tickMin) * Fluidos.tickMin * 5; if(spreadBase < 0) spreadBase = 0; spreadAlvo = 2*spreadMin + spreadBase - spreadAlpha; if(spreadAlvo < 0) spreadAlvo = Fluidos.tickMin; spreadAlvoRet = spreadAlvo; spreadStopRet = spreadStop; return spread; } //+------------------------------------------------------------------+ //| 5.5 - FUNCAO QUE CALCULA A MEDIA DE PRECOS | //+------------------------------------------------------------------+ void GetPrecosPassados(MqlTick &ArrayTick[], double &precos[], int T) { if(CopyTicks(Symbol(),ArrayTick,COPY_TICKS_TRADE,0,T) != -1) { ArraySetAsSeries(ArrayTick,true); for(int i=0;i0 ; i--) { if(i == n) { fatorial = i; } else { fatorial = fatorial * i; } } return fatorial; } //+===================================================================================================================================================================================+ //| FIM DO PROGRAMA //+===================================================================================================================================================================================+