Arbitragem no Forex: Um bot market maker simples de sintéticos para começar
Introdução: do trader de varejo ao pensamento institucional
Muitas vezes me perguntam como cheguei ao desenvolvimento do TrisWeb_Optimized. A história começa em 2016, quando mergulhei pela primeira vez no mundo do Forex, com a ingenuidade de um iniciante e a crença no trading baseado em indicadores. Naquela época, eu ainda acreditava no "Santo Graal" do trading, uma combinação mágica de indicadores que supostamente transformaria $1000 em um milhão em um ano.
Minha mente foi revolucionada em 2017, quando, após uma série de perdas dolorosas, comecei a estudar como os grandes players realmente operam. Não os que falam de seus "lucros milionários" no YouTube, mas os verdadeiros: bancos, hedge funds e empresas de prop trading.
E foi isso que descobri: eles não usam estratégias cheias de indicadores complexos. Eles aplicam princípios matemáticos, gestão de risco, arbitragem, market making e outras abordagens baseadas em uma compreensão fundamental dos mecanismos de mercado. Foi então que tomei a decisão: é preciso operar como um grande player, ou simplesmente não operar.
Os três anos seguintes foram dedicados ao estudo dos métodos institucionais de trading. Mergulhei no mundo das correlações intermercado, da arbitragem estatística e do trading algorítmico. Experimentei com Python e MQL, criando protótipos de sistemas que imitavam as abordagens dos grandes participantes do mercado, mas adaptados à realidade do trader de varejo, com suas limitações de capital e tecnologia.
Em meio a um dos períodos mais turbulentos da história dos mercados financeiros, em janeiro de 2020, nasceu o Tris_Optimized — minha resposta à pergunta: "Como um trader de varejo pode aplicar estratégias institucionais?"
Esse EA (Expert Advisor) não tenta prever os movimentos do mercado, não se baseia em indicadores de análise técnica e não depende da "intuição" do trader. Em vez disso, ele calcula matematicamente potenciais desequilíbrios entre três pares de moedas correlacionados e posiciona uma grade de ordens pronta para capturar esses desequilíbrios assim que eles surgirem.
Após cinco anos de operação contínua em condições reais de mercado, o Tris_Optimized provou sua viabilidade. Ele sobreviveu à pandemia, aos picos inflacionários, às mudanças nas taxas de juros e às crises geopolíticas, e continua gerando lucro de maneira estável (nos raros períodos em que realmente opero, e não passo noites inteiras entre ideias de código e o próprio código). Ele não é um sistema milagroso que promete ganhos absurdos, mas uma ferramenta de trabalho confiável baseada em princípios fundamentais do trading institucional.
Hoje, essa base de pensamento institucional me permite operar com sucesso em diferentes mercados. Embora eu tenha me concentrado, nos últimos anos, em estratégias baseadas em aprendizado de máquina, as abordagens de arbitragem continuam sendo uma parte essencial do meu arsenal de trading. A combinação de métodos estatísticos de ML com os padrões fundamentais de mercado utilizados por traders institucionais me oferece uma vantagem significativa. Fui convidado até para um pequeno e praticamente desconhecido hedge fund, embora isso soe mais impressionante do que é: além de mim, há apenas um gerente de risco e uma gestora, e estamos nos preparando para implementar uma infraestrutura no MetaTrader 5 voltada a hedge funds.
Algumas semanas atrás, eu estava revisando meu armazenamento em nuvem e encontrei um arquivo com meus antigos robôs de trading. Entre eles estava o Tris_Optimized, um dos meus primeiros projetos que, apesar de sua "simplicidade" em comparação com os sistemas modernos de ML, ainda funciona e entrega resultados. Eu o executei em uma conta de teste e fiquei surpreso: mesmo sem otimização para as condições atuais de mercado, ele apresentou resultado positivo.
Foi então que decidi compartilhar esse código com a comunidade. Não porque se trate de um sistema revolucionário que fará você milionário em um mês. A porque esse código é um excelente exemplo de como aplicar uma abordagem institucional ao trading, mesmo sendo um trader de varejo. É uma espécie de ponte entre dois mundos, que pode ajudar você a fazer a mesma transição que um dia eu fiz.
Neste artigo, vou revelar a mecânica de funcionamento do TrisWeb_Optimized, explicar sua arquitetura e compartilhar minha experiência de configuração e otimização. Pronto para mergulhar no mundo do trading algorítmico profissional? Então vamos lá.
Arbitragem triangular no Forex: o princípio do triângulo EURUSD-GBPUSD-EURJPY
Vamos começar pelo fato de que a arbitragem triangular no mercado Forex é uma verdadeira caça a fantasmas. Imagine a situação: você monitora simultaneamente EURUSD, GBPUSD e EURJPY, tentando capturar um breve desequilíbrio de preços, quando o ciclo fechado EUR→USD→GBP→EUR oferece pelo menos alguns pips de lucro líquido. Mas a verdade é que oportunidades puras de arbitragem são tão raras quanto unicórnios no centro de São Paulo. Os institucionais, com seus algoritmos de alta frequência e acesso direto à liquidez, consomem essas oportunidades mais rápido do que você consegue piscar.
Foi exatamente por isso que criei o TrisWeb_Optimized, um EA que não espera por condições ideais, mas constrói uma teia tridimensional de ordens, pronta para capturar lucros a partir das oscilações naturais do mercado. Não se trata de uma arbitragem clássica no sentido acadêmico do termo, mas de uma estratégia de guerrilha do trader varejista, que utiliza as inter-relações matemáticas entre três pares de moedas.
Pares de moedas sintéticos em MQL5: a porta secreta para a arbitragem
O que são pares de moedas sintéticos? É uma abstração matemática que criamos a partir de instrumentos realmente negociados. Por exemplo, a partir das cotações de EURUSD e GBPUSD, podemos calcular o par sintético EURGBP, que, em tese, deveria corresponder exatamente ao EURGBP real. No entanto, no mundo real, sempre existem pequenas divergências, e é nelas que está o nosso pão de cada dia.
O TrisWeb_Optimized não cria pares sintéticos de forma explícita, mas toca suas cordas invisíveis. Abaixo, há um trecho de código no qual obtemos os preços atuais de cada símbolo, o que é o primeiro passo na busca por desequilíbrios:
// Получаем текущие цены для каждого символа double priceSymbol1 = GetCurrentPrice(Symbol1); double priceSymbol2 = GetCurrentPrice(Symbol2); double priceSymbol3 = GetCurrentPrice(Symbol3);
Essas três linhas são o ponto de entrada em um espaço multidimensional de oportunidades, onde as menores discrepâncias podem se transformar em dinheiro real.
Arquitetura do TrisWeb_Optimized: a máquina que sobreviveu à pandemia
Quando escrevi as primeiras linhas do TrisWeb_Optimized em janeiro de 2020, o mundo estava à beira de uma pandemia, de choques no mercado e de uma volatilidade insana. Ninguém poderia prever que esse simples EA seria submetido ao seu batismo de fogo em algumas das condições de mercado mais extremas das últimas décadas. E sabe de uma coisa? Ele sobreviveu. Não apenas sobreviveu, mas também prosperou.
O coração do sistema bate na função OnTick(), que é acionada a cada variação de preço, analisando todo o cenário em três frentes simultaneamente:
void OnTick() { // Подсчет ордеров и прибыли int ordersCount1 = 0, ordersCount2 = 0, ordersCount3 = 0; double profit1 = 0, profit2 = 0, profit3 = 0; // Подсчет отложенных ордеров CountPendingOrders(ordersCount1, ordersCount2, ordersCount3); // Подсчет открытых позиций и их профита CountOpenPositions(ordersCount1, ordersCount2, ordersCount3, profit1, profit2, profit3); // ... остальной код }
À primeira vista, parece um código comum. Porém, por trás dessas linhas, esconde-se uma arquitetura modular elegante: cada aspecto do sistema está isolado em sua própria função, como um órgão dentro de um organismo perfeitamente sincronizado. Sem confusão, sem desordem, apenas uma clara separação de responsabilidades.
Ajuste dos parâmetros da grade: uma dança com a volatilidade
O mercado Forex se assemelha a um oceano: o par EUR/USD flui lenta e majestosamente, como uma corrente profunda, enquanto o par EUR/JPY pode explodir como um tsunami repentino. Tentar operar esses pares com os mesmos parâmetros é um caminho certo para a frustração. Por esse motivo, o TrisWeb_Optimized permite configurar parâmetros individuais de grade para cada instrumento:
input group "Step Settings" input int Step01_Symbol1 = 40; // Начальный шаг для Symbol1 (в пунктах) input int Step02_Symbol1 = 60; // Шаг между ордерами для Symbol1 (в пунктах) input int Step01_Symbol2 = 40; // Начальный шаг для Symbol2 (в пунктах) input int Step02_Symbol2 = 60; // Шаг между ордерами для Symbol2 (в пунктах) input int Step01_Symbol3 = 40; // Начальный шаг для Symbol3 (в пунктах) input int Step02_Symbol3 = 60; // Шаг между ордерами для Symbol3 (в пунктах)
Ao longo de cinco anos trabalhando com esse sistema, desenvolvi um tipo de ritual: para pares mais tranquilos, como o EURUSD, uso espaçamentos padrão de 40 e 60 pontos; para os JPY-crosses mais explosivos, aumento para 50 e 80. É como ajustar a sensibilidade da vara de pescar conforme o tipo de peixe: com a mesma abordagem, você acaba pegando tudo ou nada.
Otimização do tamanho dos lotes: o DNA adaptativo do sistema
Um tamanho de lote fixo é coisa de iniciante. O profissional sabe que o volume deve respirar junto com o saldo da conta. O TrisWeb_Optimized faz isso por meio da função CalculateOptimalLotSize(), que considero meu pequeno orgulho técnico:
double CalculateOptimalLotSize(string symbol, double baseSize) { if(!AutoLotOptimization) return baseSize; double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE); double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); double minLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); // ... остальной код расчета }Essa função é um verdadeiro canivete suíço. Ela leva em conta o saldo atual, o percentual de risco configurado, o valor do pip para o símbolo em questão, as restrições da corretora quanto ao tamanho mínimo e ao passo de lote e, o que mais me orgulha, ajusta automaticamente os cálculos para moedas exóticas:
// Корректировка для пар с JPY и других экзотических валют string quoteCurrency = StringSubstr(symbol, 3, 3); if(quoteCurrency == "JPY" || quoteCurrency == "XAU" || quoteCurrency == "XAG") pointCost *= 100.0;
Para quem não está familiarizado: o valor de um pip nos pares com iene japonês é 100 vezes menor do que nos pares principais. Esquecer esse ajuste faz com que seu robô ou opere com volumes microscópicos ou destrua sua conta em uma única sessão.
Gestão do tempo de operação do EA: o algoritmo com ritmo circadiano
O mercado Forex opera 24 horas por dia, mas isso não significa que seu EA deva fazer o mesmo. Existem períodos em que é melhor ficar de fora, como a sessão noturna, que costuma apresentar spreads amplos e movimentos artificiais, trazendo mais problemas do que oportunidades. O TrisWeb_Optimized possui um "ritmo circadiano" interno graças à função IsWorkTime():
bool IsWorkTime() { MqlDateTime currentTime; TimeToStruct(TimeLocal(), currentTime); datetime currentTimeSeconds = HoursMinutesToSeconds(currentTime.hour, currentTime.min); datetime startTimeSeconds = HoursMinutesToSeconds(StartTimeHour, StartTimeMin); datetime endTimeSeconds = HoursMinutesToSeconds(EndTimeHour, EndTimeMin); return (startTimeSeconds <= currentTimeSeconds && currentTimeSeconds <= endTimeSeconds); }E a função CheckNewDayAndWorkTime() adiciona ao EA uma característica quase humana: a capacidade de "recomeçar do zero" a cada novo dia:
void CheckNewDayAndWorkTime() { if(IsNewDay && IsNewDayReset && IsWorkTime()) { DeleteAllOrders(); IsNewDay = false; } if(!IsWorkTime()) { IsNewDay = true; } }
Isso é especialmente valioso no longo prazo: o sistema não acumula o "peso" de ordens antigas, mas renova constantemente a grade de ordens conforme as condições atuais do mercado.
Algoritmo de saída das posições: a arte de sair na hora certa
No trading, assim como na vida, não basta entrar no momento certo: é preciso também saber sair. O TrisWeb_Optimized utiliza um critério simples e eficaz: o fechamento das posições ocorre quando o lucro total atinge um nível pré-definido:
// Общее количество ордеров int totalOrders = ordersCount1 + ordersCount2 + ordersCount3; double totalProfit = profit1 + profit2 + profit3; // Если нет ордеров - создаем, если есть - проверяем на прибыль if(totalOrders == 0) { if(IsWorkTime()) { PlaceInitialOrders(); } } else if(totalProfit > Profit) { DeleteAllOrders(); }Mas o diabo, como sempre, mora nos detalhes. O sistema não considera apenas o "lucro bruto", mas o resultado líquido, levando em conta swaps e comissões:
double swap = PositionGetDouble(POSITION_SWAP); double profit = PositionGetDouble(POSITION_PROFIT); double commission = PositionGetDouble(POSITION_COMMISSION); double totalProfitForPosition = profit + swap + commission;
Isso é fundamental para a operação de longo prazo, especialmente quando há posições mantidas durante a noite, quando os swaps são aplicados. Caso contrário, o sistema pode ignorar combinações realmente lucrativas ou, pior, considerar lucrativas operações que, na verdade, geram prejuízo por causa dos swaps negativos.
Ajuste fino da execução das ordens: o pacto com o demônio do mercado
No mundo do trading de alta frequência, a qualidade da execução pode ser o fator decisivo entre lucro e prejuízo. O TrisWeb_Optimized utiliza estruturas de baixo nível do MQL5 para garantir o máximo controle sobre o processo de envio e execução das ordens:
bool OpenBuyStop(string symbol, double volume, double openPrice) { MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_PENDING; request.symbol = symbol; request.volume = volume; request.type = ORDER_TYPE_BUY_STOP; request.price = openPrice; request.deviation = Deviation; request.magic = EXPERT_MAGIC; if(UseCommentsInOrders) request.comment = OrderComment; if(!OrderSend(request, result)) { Print("OrderSend error ", GetLastError(), " retcode: ", result.retcode); return false; } return true; }É preciso prestar atenção especial ao parâmetro Deviation, pois ele define quão distante do preço solicitado a ordem pode ser executada:
input int Deviation = 3; // Допустимое отклонение цены
Esse é o seu pacto com o "demônio do mercado": "Estou disposto a aceitar uma execução até 3 pontos pior do que o preço solicitado, mas não mais que isso." Em períodos de alta volatilidade, essa diferença pode significar a distância entre uma ordem executada e uma oportunidade perdida. Se o valor for muito pequeno, suas ordens serão rejeitadas por requotes; se for grande demais, você corre o risco de ser executado a um preço inesperadamente ruim.
Exibição e análise em tempo real: os olhos e ouvidos do trader
Quando comecei o desenvolvimento do TrisWeb_Optimized, eu já entendia que um dos principais problemas de muitos EAs é que eles funcionam como uma "caixa-preta", sem permitir ao trader entender o que realmente está acontecendo. Por isso, adicionei uma saída detalhada de informações por meio da função DisplayInfo():
void DisplayInfo(int totalOrders, double totalProfit, double profit1, double profit2, double profit3, int count1, int count2, int count3) { string info = ""; if(AutoLotOptimization) { double lot1 = CalculateOptimalLotSize(Symbol1, Lot_Symbol1); double lot2 = CalculateOptimalLotSize(Symbol2, Lot_Symbol2); double lot3 = CalculateOptimalLotSize(Symbol3, Lot_Symbol3); info += "Auto Lot: " + Symbol1 + "=" + DoubleToString(lot1, 2) + ", " + Symbol2 + "=" + DoubleToString(lot2, 2) + ", " + Symbol3 + "=" + DoubleToString(lot3, 2) + "\n"; } // ... остальной код формирования информации Comment(info); }Você pode escolher entre o modo básico de exibição (para quem prefere o minimalismo) e a análise detalhada, que inclui a decomposição por cada par de moedas:
input bool DisplayDetailedInfo = false; // Показывать детальную информацию
É como a diferença entre o painel simples de um carro antigo, com apenas velocímetro e indicador de combustível, e o cockpit moderno cheio de sensores e monitores — a escolha depende do seu estilo de condução.
Veja como se comportou um dos antigos conjuntos de parâmetros:
Escalabilidade do sistema: de um bot simples a um império de trading
O TrisWeb_Optimized não é apenas um EA pronto, mas uma base sólida para construir sua própria estrutura de arbitragem. Ao longo de cinco anos de evolução, eu o modifiquei inúmeras vezes, adicionando novas funções e aprimorando as existentes. Há várias direções pelas quais você pode expandir o sistema:
A integração com Python abre possibilidades imensas para a análise de correlações e aplicação de métodos de aprendizado de máquina. Imagine poder analisar não apenas as cotações atuais, mas também padrões históricos de interação entre três pares de moedas, prevendo assim os desequilíbrios mais prováveis.
As notificações via Telegram API adicionam mobilidade à sua estratégia — você se mantém informado sobre eventos importantes mesmo longe do terminal de trading. Isso é especialmente valioso quando o EA está em execução em um VPS remoto.
Expandir o sistema para mais pares de moedas transforma o TrisWeb em uma plataforma de arbitragem completa. Por que se limitar a três instrumentos se é possível criar uma rede com dezenas de pares interconectados, monitorando centenas de potenciais oportunidades de arbitragem?
Para realizar todas essas modificações, basta fazer pequenas alterações no código existente, preservando sua estrutura principal e a lógica de funcionamento. É como construir novos cômodos em uma casa já pronta: o alicerce está pronto, basta expandir o espaço habitável.
Em vez de conclusão
Cinco anos atrás, quando a primeira versão do TrisWeb_Optimized nasceu, eu não fazia ideia do caminho que ela percorreria. Ela sobreviveu a tempestades de mercado, a períodos de volatilidade extrema e a fases de aparente calmaria. Evoluiu de um simples script para um sistema de trading maduro. Mas, acima de tudo, nunca deixou de gerar lucro.
Na próxima parte deste artigo, vamos mergulhar nos aspectos práticos da configuração do TrisWeb_Optimized, analisar exemplos reais de operação do sistema e compartilhar segredos de otimização de parâmetros para diferentes condições de mercado. Fique conosco, pois o mais interessante ainda está por vir!
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/17424
Aviso: Todos os direitos sobre esses materiais pertencem à MetaQuotes Ltd. É proibida a reimpressão total ou parcial.
Esse artigo foi escrito por um usuário do site e reflete seu ponto de vista pessoal. A MetaQuotes Ltd. não se responsabiliza pela precisão das informações apresentadas nem pelas possíveis consequências decorrentes do uso das soluções, estratégias ou recomendações descritas.
Arbitragem no trading Forex: Análise dos movimentos de moedas sintéticas e seu retorno à média
Otimização por neuroboides — Neuroboids Optimization Algorithm (NOA)
Arbitragem de swap no Forex: Montando uma carteira sintética e criando um fluxo estável de swaps
Visualização de estratégias em MQL5: distribuindo os resultados da otimização em gráficos de critérios
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
Abordagem interessante. Iniciado como está, sem otimização. Ela mantém o equilíbrio, há um aumento em pequenas etapas.
Se quiser, você pode mover o fechamento da grade para o final do dia, antes da formação do swap. No momento, a grade é fechada no início da negociação. Ou não usar o fechamento diário de forma alguma.
Definitivamente, há espaço para desenvolvimento e aplicação em soluções complexas.
Vamos em frente!