
Estudando o indicador de perfil de mercado — Market Profile: O que é e como funciona?
Conteúdo
Market Profile — o que é?
Peter Steidlmayer desenvolveu o conceito de Perfil de Mercado nos anos 1980 junto com a Bolsa de Mercadorias de Chicago. Traders que usam esse método destacam sua utilidade para uma compreensão mais profunda do mercado e para aumentar a eficácia da negociação.
O Perfil de Mercado não é um indicador técnico tradicional, e não fornece sinais diretos de negociação. Mas ele complementa o sistema de trading, ajudando a organizar os dados e a identificar quem está no controle do mercado, o que é o valor justo e quais fatores influenciam o movimento dos preços.
O Perfil de Mercado mostra a organização das negociações com base em tempo, preço e volume. A cada dia, forma-se um intervalo com uma área de valor que representa o equilíbrio entre compradores e vendedores. Nessa zona os preços oscilam, e o Market Profile ajuda os traders a interpretar essas variações tanto durante quanto após o encerramento das negociações. Ele se baseia na curva de distribuição normal, onde cerca de 70% do valor está dentro de um desvio padrão a partir da média. Em outras palavras, é uma ferramenta de análise que mostra a distribuição de volumes ou do tempo em que o preço permaneceu em determinados níveis. Ela ajuda os traders a entender onde ocorreram os maiores negócios e a identificar níveis-chave de demanda e oferta.
Ao utilizar o Perfil de Mercado, existem alguns conceitos ligados ao comportamento do mercado que são representados direta ou indiretamente no gráfico. O timeframe recomendado para análise é M30.
A primeira hora de negociação forma o padrão principal do dia de trading e serve de base para estudar a atividade dos participantes do mercado durante toda a sessão. Esse período é importante para entender o que os traders estão fazendo na busca por um preço em que comprador e vendedor concordem com uma negociação.
Existem duas categorias de participantes do mercado:
- day-timeframe trader — trader de curto prazo que opera dentro do dia com grandes volumes em poucos ticks;
- other-timeframe trader — trader que opera em outros períodos e impulsiona o preço para novos níveis.
Vamos analisar alguns conceitos básicos que ajudam a entender melhor o Perfil de Mercado.
- Initial balance (balanço inicial) — faixa de preços do mercado durante a primeira hora da sessão de negociação (duas barras de 30 minutos após a abertura da sessão).
- Range — intervalo, altura absoluta de todo o Perfil de Mercado.
- Range extension — extensão do intervalo quando o preço se move em relação ao balanço inicial.
- Value area — zona de valor, faixa de preços que abrange 70% da atividade de negociação.
- Point of control (POC — ponto de controle) — a linha mais longa do perfil, que ao mesmo tempo está mais próxima do centro do intervalo.
- Closing range (faixa de fechamento) — posiciona-se próxima ao encerramento da sessão de negociação.
- Buying/Selling tail (cauda de compra/venda). A presença dessas caudas indica atividade intensa por parte dos traders "other-timeframe".
O comprimento pequeno das caudas indica agressividade suficiente dos traders "other-timeframe", tanto do lado comprador quanto do lado vendedor.
Para ler o Market Profile, é possível seguir estes princípios básicos:
- Definição "Preço-Volume" (Price-Volume)
O Market Profile mostra em quais níveis de preço houve o maior volume. As linhas ou blocos no gráfico (geralmente horizontais) mostram quanto tempo o preço permaneceu em determinado nível ou qual volume foi negociado ali. Linhas mais longas significam mais tempo ou maior volume — esses são níveis-chave de suporte e resistência. - Ponto de controle (POC — Point of Control)
É o nível de preço onde ocorreu o maior volume de negociações no período. Ele frequentemente funciona como um forte nível de suporte ou resistência, já que ali o preço é o mais "aceitável" para os participantes do mercado. - Zonas de preço justo e injusto (Value Area e Non-Value Area)
- Value Area: normalmente representa cerca de 70% do volume de negociações do período. É o intervalo onde o preço encontrou, na maior parte do tempo, um "equilíbrio" entre oferta e demanda.
- Non-Value Area: níveis acima ou abaixo da Value Area são considerados zonas de baixo interesse. Se o preço vai para essas zonas, ele pode rapidamente retornar à Value Area ou continuar se movimentando por causa do desequilíbrio entre oferta e demanda.
- Identificação de tendências e consolidações
- Dia de tendência: O Market Profile "se alonga" em uma direção quando o mercado se move de forma consistente para cima ou para baixo. Nesses casos, o preço não permanece em níveis específicos, mas avança, criando novas zonas de interesse. Um dia de tendência apresenta um balanço inicial pequeno, representando menos de 25% do intervalo total do dia. Na prática, isso indica um domínio significativo de compradores ou vendedores, com forte expansão do intervalo em uma das direções.
- Dia de consolidação: o perfil se concentra em torno de um único nível, e a Value Area permanece estreita. Isso indica equilíbrio e ausência de tendência forte.
- Dia sem tendência: caracteriza-se por um balanço inicial estreito, que posteriormente abrange o intervalo total de preços do dia.
- Dia normal: esse tipo de dia apresenta um balanço inicial amplo, representando cerca de 80% do intervalo total. É o tipo mais comum de dia de negociação.
- Variação normal de um dia normal: o balanço inicial dessa estrutura representa aproximadamente 50% do intervalo do dia. Com isso, ocorre uma expansão do intervalo em uma ou outra direção.
- Dia neutro: esse perfil não é definido pelo seu balanço inicial, apresenta expansão do intervalo para ambos os lados, e o dia termina próximo ao centro do intervalo.
- Dia de tendência: O Market Profile "se alonga" em uma direção quando o mercado se move de forma consistente para cima ou para baixo. Nesses casos, o preço não permanece em níveis específicos, mas avança, criando novas zonas de interesse. Um dia de tendência apresenta um balanço inicial pequeno, representando menos de 25% do intervalo total do dia. Na prática, isso indica um domínio significativo de compradores ou vendedores, com forte expansão do intervalo em uma das direções.
- Compreensão dos extremos e reação do preço
- Se o preço atinge novos níveis com baixo volume e retorna rapidamente ao POC ou à Value Area, isso pode indicar um recuo.
- Se o preço continua a ser negociado fora da Value Area e cria um novo POC, isso sinaliza o possível início de uma nova tendência.
- Aplicação prática do Market Profile
- Para encontrar pontos de entrada: identifique níveis de suporte e resistência usando o POC e os limites da Value Area. Aguarde recuos nesses níveis ou rompimentos na direção da tendência.
- Para definir stop-loss e metas: use o POC e os limites superior/inferior da Value Area como níveis para posicionar stops de proteção e para realização de lucro.
O Market Profile clássico é baseado em TPOs (oportunidades de tempo-preço), que utilizam letras maiúsculas do alfabeto latino. Cada letra representa um período de 30 minutos da sessão de negociação.
Market Profile no terminal MetaTrader 5
No terminal cliente MetaTrader 5, no diretório de indicadores \MQL5\Indicators\Free Indicators\, está disponível uma versão simples do Perfil de Mercado, cujo código está no arquivo MarketProfile.mq5. Esse indicador, diferentemente da versão clássica, constrói perfis verticais de volume por sessão (Ásia, Europa, América), visualizando as zonas onde o preço permaneceu por mais tempo. Ele analisa barras intradiárias e as divide em três períodos de tempo, correspondentes às diferentes sessões do mercado. O indicador calcula quanto tempo o preço permaneceu em cada nível durante essas sessões e os exibe visualmente como retângulos no gráfico.
Pontos principais para leitura desse indicador:
- Divisão por sessões de negociação:
- O dia inteiro é dividido em três sessões: Asiática, Europeia e Americana.
- As zonas coloridas no gráfico mostram o tempo que o preço passou em cada nível durante cada sessão.
- Níveis de preço:
- Cada nível de preço é colorido conforme a sessão e o tempo que o preço permaneceu nesse nível. Os níveis onde o preço ficou mais tempo são considerados níveis importantes, pois houve negociação ativa nesses pontos.
- POC (Point of Control):
- O indicador não calcula diretamente o POC, mas é possível identificá-lo visualmente pelos níveis com as zonas coloridas mais extensas — essas são as zonas de controle, indicando os níveis-chave de demanda e oferta.
- Zonas de valor (Value Areas):
- Assim como no Market Profile padrão, as áreas com maior concentração de volume (onde o preço permaneceu por mais tempo) podem ser vistas como níveis aos quais o preço tende a retornar.
Dessa forma, o indicador Market Profile neste código ajuda a entender em quais níveis do dia se concentrou a principal atividade, destacando níveis de suporte e resistência para cada sessão de negociação.
Vamos entender como funciona esse indicador.
Estrutura e princípios
Nos parâmetros de entrada do indicador são definidos:
- o número de dias para os quais o perfil deve ser exibido,
- o número do dia mais próximo ao atual:
- 0 — o dia atual,
- 1 — o anterior,
- 2 — o antepenúltimo, e assim por diante,
- as cores utilizadas para desenhar as sessões (asiática, europeia e americana),
- os horários de abertura das sessões europeia e americana (a sessão asiática se inicia com a abertura do dia),
- o multiplicador do comprimento dos segmentos do histograma:
//--- input parameters input uint InpStartDate =0; /* day number to start calculation */ // 0 - current, 1 - previous, etc. input uint InpShowDays =3; /* number of days to display */ // starting with and including the day in InpStartDate input int InpMultiplier =1; /* histogram length multiplier */ input color InpAsiaSession =clrGold; /* Asian session */ input color InpEuropeSession =clrBlue; /* European session */ input color InpAmericaSession =clrViolet; /* American session */ input uint InpEuropeStartHour =8; /* European session opening hour */ input uint InpAmericaStartHour=14; /* American session opening hour */
Na inicialização do indicador, cria-se um identificador único para os nomes dos objetos, utilizando os últimos quatro dígitos do número de milissegundos desde o início do sistema:
//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- create a prefix for object names string number=StringFormat("%I64d", GetTickCount64()); ExtPrefixUniq=StringSubstr(number, StringLen(number)-4); Print("Indicator \"Market Profile\" started, prefix=", ExtPrefixUniq); return(INIT_SUCCEEDED); }
Esse número será usado posteriormente para nomear os objetos gráficos do indicador e, com o mesmo prefixo, os objetos serão removidos durante a desinicialização:
//+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- after use, delete all graphical objects created by the indicator Print("Indicator \"Market Profile\" stopped, delete all objects with prefix=", ExtPrefixUniq); ObjectsDeleteAll(0, ExtPrefixUniq, 0, OBJ_RECTANGLE); ChartRedraw(0); }
Então, como o indicador é estruturado? Qual é a lógica por trás do seu desenho? Vamos imaginar que o tamanho completo da vela diária, do seu Low até o High, seja o tamanho de uma tabela. Nesse caso, as linhas da tabela representam os níveis de preço: cada ponto de preço corresponde a uma linha da tabela. As colunas da tabela, na forma mais simples, representam a distância de um barra intradiária até a próxima. A linha de índice zero representa o menor preço, igual ao Low da barra. O preço com índice 1 é o Low da barra mais um ponto. Consequentemente, a linha que representa o High da barra é a linha com índice igual ao Low da barra mais a quantidade de pontos entre o Low e o High da barra.
Se agora for criado um array simples correspondente às linhas dessa tabela, então, no índice zero desse array será armazenada a quantidade de barras que tocaram o preço Low da barra ao longo do movimento do preço durante o dia. Da mesma forma, todas as outras células desse array armazenarão a quantidade de vezes que o preço passou por esses níveis.
Como isso é determinado? É bem simples. Como o Low da barra diária na abertura do dia corresponde ao índice zero do array, é possível calcular os índices de todas as outras barras intradiárias: o índice da linha correspondente à barra seguinte à barra de abertura é o Low dessa barra menos o Low da abertura do dia, em pontos. O último índice dessa barra será o High da barra menos o Low da abertura do dia.
Na ilustração abaixo, são mostrados os índices de início e fim no array Array para quatro barras intradiárias de seis horas: Bar0, Bar1, Bar2 e Bar3:
Se agora marcarmos no array a quantidade de barras que passaram por determinados níveis de preço, e desenharmos retângulos do perfil de mercado, obteremos uma visualização semelhante no array e no gráfico:
O array Array é limpo a cada novo tick, recebe um novo tamanho correspondente ao Range da barra diária, e seus índices são preenchidos novamente com o número de barras que passaram por cada nível de preço. Assim, o perfil de mercado é preenchido dinamicamente e exibe no gráfico informações atualizadas sobre o estado do mercado. Quanto mais tempo o preço permanecer em determinado nível (quanto mais barras incluírem esse nível), mais longa será a linha que representa esse nível.
Vamos ver como isso é implementado no código do indicador:
//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //--- opening time of the current daily bar datetime static open_time=0; //--- number of the last day for calculations //--- (if InpStartDate = 0 and InpShowDays = 3, lastday = 3) //--- (if InpStartDate = 1 and InpShowDays = 3, lastday = 4) etc ... uint lastday=InpStartDate+InpShowDays; //--- if the first calculation has already been made if(prev_calculated!=0) { //--- get the opening time of the current daily bar datetime current_open=iTime(Symbol(), PERIOD_D1, 0); //--- if we do not calculate the current day if(InpStartDate!=0) { //--- if the opening time was not received, leave if(current_open==open_time) return(rates_total); } //--- update opening time open_time=current_open; //--- we will only calculate one day from now on, since all other days have already been calculated during the first run lastday=InpStartDate+1; } //--- in a loop for the specified number of days (either InpStartDate+InpShowDays on first run, or InpStartDate+1 on each tick) for(uint day=InpStartDate; day<lastday; day++) { //--- get the data of the day with index day into the structure MqlRates day_rate[]; //--- if the indicator is launched on weekends or holidays when there are no ticks, you should first open the daily chart of the symbol //--- if we have not received bar data for the day index of the daily period, we leave until the next call to OnCalculate() if(CopyRates(Symbol(), PERIOD_D1, day, 1, day_rate)==-1) return(prev_calculated); //--- get daily range (Range) in points double high_day=day_rate[0].high; double low_day=day_rate[0].low; double point=SymbolInfoDouble(Symbol(), SYMBOL_POINT); int day_size=(int)((high_day-low_day)/point); //--- prepare arrays for storing price level rectangles int boxes_asia[], boxes_europe[], boxes_america[]; //--- array sizes equal to the number of points in the day range ArrayResize(boxes_asia, day_size); ArrayResize(boxes_europe, day_size); ArrayResize(boxes_america, day_size); //--- zero out the arrays ZeroMemory(boxes_asia); ZeroMemory(boxes_europe); ZeroMemory(boxes_america); //--- get all intraday bars of the current day MqlRates bars_in_day[]; datetime start_time=day_rate[0].time+PeriodSeconds(PERIOD_D1)-1; datetime stop_time=day_rate[0].time; //--- if the indicator is launched on weekends or holidays when there are no ticks, you should first open the daily chart of the symbol //--- if it was not possible to get the bars of the current timeframe for the specified day, leave until the next call of OnCalculate() if(CopyRates(Symbol(), PERIOD_CURRENT, start_time, stop_time, bars_in_day)==-1) return(prev_calculated); //--- we go through all the bars of the current day in a loop and mark the price cells that the bars fall into int size=ArraySize(bars_in_day); for(int i=0; i<size; i++) { //--- calculate the range of price level indices in the daily range int start_box=(int)((bars_in_day[i].low-low_day)/point); // index of the first cell of the price array corresponding to the Low price of the current i bar int stop_box =(int)((bars_in_day[i].high-low_day)/point); // index of the last cell of the price array corresponding to the High price of the current i bar //--- get the bar hour by the loop index MqlDateTime bar_time; TimeToStruct(bars_in_day[i].time, bar_time); uint hour=bar_time.hour; //--- determine which session the bar belongs to by the bar hour //--- American session if(hour>=InpAmericaStartHour) { //--- in the American session array, in cells from start_box to stop_box, increase the bar counters for(int ind=start_box; ind<stop_box; ind++) boxes_america[ind]++; } //--- Europe or Asia else { //--- European session if(hour>=InpEuropeStartHour && hour<InpAmericaStartHour) //--- in the European session array, in cells from start_box to stop_box, increase the bar counters for(int ind=start_box; ind<stop_box; ind++) boxes_europe[ind]++; //--- Asian session else //--- in the Asian session array, in cells from start_box to stop_box, increase the bar counters for(int ind=start_box; ind<stop_box; ind++) boxes_asia[ind]++; } } //--- draw a market profile based on the created arrays of price levels //--- market profile on the chart is drawn with segments of colored lines using the color specified in the settings for each trading session //--- segments are drawn as rectangle objects with the height of the rectangle equal to one price point and the width equal to the distance to the next bar to the right //--- define the day for the name of the graphical object and the width of the rectangle string day_prefix=TimeToString(day_rate[0].time, TIME_DATE); int box_length=PeriodSeconds(PERIOD_CURRENT); //--- Asian session //--- in a loop by the number of points of the daily bar for(int ind=0; ind<day_size; ind++) { //--- if the Asian session array is full if(boxes_asia[ind]>0) { //--- get the next price by adding the number of 'ind' points to the Low price of the daily bar //--- get the start time of the segment (opening time of the daily bar) //--- and the end time of the segment (opening time of the daily bar + the number of bars stored in the 'ind' cell of the boxes_asia[] array) double price=low_day+ind*point; datetime time1=day_rate[0].time; datetime time2=time1+boxes_asia[ind]*box_length*InpMultiplier; //--- create a prefix for the name of the Asian session graphical object string prefix=ExtPrefixUniq+"_"+day_prefix+"_Asia_"+StringFormat("%.5f", price); //--- draw a rectangle (line segment) at the calculated coordinates with the color for the Asian session DrawBox(prefix, price, time1, time2, InpAsiaSession); } } //--- European session for(int ind=0; ind<day_size; ind++) { //--- if the European session array is full if(boxes_europe[ind]>0) { //--- get the next price by adding the number of 'ind' points to the Low price of the daily bar //--- get the start time of the segment (opening time of the daily bar + time of the right edge of the Asian session profile) //--- and the end time of the segment (start time of the European session segment + the number of bars stored in the 'ind' cell of the boxes_europe[] array) double price=low_day+ind*point; datetime time1=day_rate[0].time+boxes_asia[ind]*box_length*InpMultiplier; datetime time2=time1+boxes_europe[ind]*box_length*InpMultiplier; //--- create a prefix for the name of the graphical object of the European session string prefix=ExtPrefixUniq+"_"+day_prefix+"_Europe_"+StringFormat("%.5f", price); //--- draw a rectangle (line segment) at the calculated coordinates with the color for the European session DrawBox(prefix, price, time1, time2, InpEuropeSession); } } //--- American session for(int ind=0; ind<day_size; ind++) { //--- if the American session array is full if(boxes_america[ind]>0) { //--- get the next price by adding the number of 'ind' points to the Low price of the daily bar //--- get the start time of the segment (opening time of the daily bar + time of the right edge of the Asian session profile + time of the right edge of the European session profile) //--- and the end time of the segment (start time of the American session segment + the number of bars stored in the 'ind' cell of the boxes_america[] array) double price=low_day+ind*point; datetime time1=day_rate[0].time+(boxes_asia[ind]+boxes_europe[ind])*box_length*InpMultiplier; datetime time2=time1+boxes_america[ind]*box_length*InpMultiplier; //--- create a prefix for the name of the American session graphical object string prefix=ExtPrefixUniq+"_"+day_prefix+"_America_"+StringFormat("%.5f", price); //--- draw a rectangle (line segment) at the calculated coordinates with the color for the American session DrawBox(prefix, price, time1, time2, InpAmericaSession); } } } //--- when the loop is complete, redraw the chart ChartRedraw(0); //--- return the number of bars for the next OnCalculate call return(rates_total); }
O código está comentado em detalhes. O indicador pode desenhar o perfil para vários dias ao mesmo tempo. Todos são desenhados dentro de um laço conforme a quantidade de dias a serem exibidos.
Análise do algoritmo principal
Vamos analisar o algoritmo do código mencionado de forma mais detalhada. Cada dia é desenhado da seguinte forma:
- dependendo do período do gráfico onde o indicador está rodando, são capturadas as barras que pertencem ao dia exibido;
MqlRates day_rate[]; if(CopyRates(Symbol(), PERIOD_D1, day, 1, day_rate)==-1) return(prev_calculated); MqlRates bars_in_day[]; datetime start_time=day_rate[0].time+PeriodSeconds(PERIOD_D1)-1; datetime stop_time=day_rate[0].time; if(CopyRates(Symbol(), PERIOD_CURRENT, start_time, stop_time, bars_in_day)==-1) return(prev_calculated);
- dentro de um laço que percorre as barras intradiárias
int size=ArraySize(bars_in_day); for(int i=0; i<size; i++)
- para a barra atual selecionada no laço, são calculados os índices de início e fim do intervalo de preços em que essa barra está localizada dentro da barra diária
int start_box=(int)((bars_in_day[i].low-low_day)/point); // index of the first cell of the price array corresponding to the Low price of the current i bar int stop_box =(int)((bars_in_day[i].high-low_day)/point); // index of the last cell of the price array corresponding to the High price of the current i bar
- é determinada a sessão à qual a barra pertence, e no array correspondente os contadores são incrementados em todas as células que estão dentro do intervalo de preços da barra intradiária
MqlDateTime bar_time; TimeToStruct(bars_in_day[i].time, bar_time); uint hour=bar_time.hour; if(hour>=InpAmericaStartHour) { for(int ind=start_box; ind<stop_box; ind++) boxes_america[ind]++; } else { if(hour>=InpEuropeStartHour && hour<InpAmericaStartHour) for(int ind=start_box; ind<stop_box; ind++) boxes_europe[ind]++; else for(int ind=start_box; ind<stop_box; ind++) boxes_asia[ind]++; }
- após a passagem completa pelo laço das barras intradiárias, cada célula dos arrays das sessões conterá a quantidade de barras que passaram por aquele preço. Todos os arrays das sessões terão o mesmo tamanho, equivalente à quantidade de pontos de preço no intervalo diário entre o Low e o High da vela diária, mas serão preenchidos de forma distinta conforme os níveis de preço que foram alcançados em cada sessão.
- Depois, em um laço que percorre todos os arrays preenchidos das sessões, objetos gráficos são exibidos no gráfico com base nas coordenadas calculadas:
for(int ind=0; ind<day_size; ind++) { if(boxes_asia[ind]>0) { double price=low_day+ind*point; datetime time1=day_rate[0].time; datetime time2=time1+boxes_asia[ind]*box_length*InpMultiplier; string prefix=ExtPrefixUniq+"_"+day_prefix+"_Asia_"+StringFormat("%.5f", price); DrawBox(prefix, price, time1, time2, InpAsiaSession); } } for(int ind=0; ind<day_size; ind++) { if(boxes_europe[ind]>0) { double price=low_day+ind*point; datetime time1=day_rate[0].time+boxes_asia[ind]*box_length*InpMultiplier; datetime time2=time1+boxes_europe[ind]*box_length*InpMultiplier; string prefix=ExtPrefixUniq+"_"+day_prefix+"_Europe_"+StringFormat("%.5f", price); DrawBox(prefix, price, time1, time2, InpEuropeSession); } } for(int ind=0; ind<day_size; ind++) { if(boxes_america[ind]>0) { double price=low_day+ind*point; datetime time1=day_rate[0].time+(boxes_asia[ind]+boxes_europe[ind])*box_length*InpMultiplier; datetime time2=time1+boxes_america[ind]*box_length*InpMultiplier; string prefix=ExtPrefixUniq+"_"+day_prefix+"_America_"+StringFormat("%.5f", price); DrawBox(prefix, price, time1, time2, InpAmericaSession); } }
- Como resultado, o gráfico apresentará o perfil de mercado para um determinado dia.
Função que desenha os segmentos de linha:
//+------------------------------------------------------------------+ //| Draw color box | //+------------------------------------------------------------------+ void DrawBox(string bar_prefix, double price, datetime time1, datetime time2, color clr) { ObjectCreate(0, bar_prefix, OBJ_RECTANGLE, 0, time1, price, time2, price); ObjectSetInteger(0, bar_prefix, OBJPROP_COLOR, clr); ObjectSetInteger(0, bar_prefix, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, bar_prefix, OBJPROP_WIDTH, 1); ObjectSetString(0, bar_prefix, OBJPROP_TOOLTIP, "\n"); ObjectSetInteger(0, bar_prefix, OBJPROP_BACK, true); }
Os segmentos são desenhados por meio de objetos gráficos do tipo retângulo (em princípio, também é possível desenhá-los como linhas de tendência, desativando as propriedades “raio à esquerda” e “raio à direita”). A função recebe as coordenadas do retângulo em forma de tempo de início e fim, e o preço, que é o mesmo para os dois lados do retângulo. Dessa forma, forma-se uma linha comum com a cor especificada nos parâmetros de entrada.
Ao executar o indicador no gráfico EURUSD M30, é possível observar esse tipo de representação do perfil de mercado:
Se, a partir de cada um dos dias anteriores, traçarmos uma linha desde o ponto Point of Control, veremos claramente níveis de preço “justo”, que podem muito bem funcionar como níveis de suporte, resistência ou de atração (por exemplo, o gap do dia atual pode muito bem ser fechado, retornando ao POC do dia anterior).
Conclusão
Ao estudar o Market Profile, você será capaz de compreender melhor a dinâmica do mercado, identificar níveis-chave e encontrar pontos eficazes para “‘entrar’” e “‘sair’” de posições. O Perfil de Mercado é diferente de um gráfico de ticks, pois une preço, volume e tempo de forma prática. Ele permite identificar níveis de equilíbrio de preço e analisar quem está no controle do mercado no momento. Isso oferece uma vantagem nas decisões de negociação, permitindo se adaptar às mudanças na percepção de valor justo pelos traders.
Tendo conhecido o indicador Market Profile fornecido com o terminal cliente MetaTrader 5, agora compreendemos toda a simplicidade do seu funcionamento, entendemos a lógica de sua construção e podemos usá-lo tanto para avaliar o mercado na forma apresentada quanto como base para criar algo mais avançado e complexo.
Para uma compreensão mais completa e comparação com outras abordagens, é possível consultar outros trabalhos sobre Perfil de Mercado disponíveis na plataforma mql5.com:
- Ferramenta “Histograma de preços” (Perfil de Mercado) e sua implementação em MQL5
- Perfil de Mercado (Market Profile) — indicador para MetaTrader 4
- MarketProfile — indicador para MetaTrader 4
- MarketProfile — indicador para MetaTrader 5
O código do indicador abordado neste artigo está completamente comentado e anexado ao final da página, ele pode ser baixado e estudado por conta própria, com base nos comentários do código.
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/16461





- 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
Base de código
Perfil de volume + intervalo v6.0
Olexiy Polyakov, 2016.06.30 12:46
Perfil de volume + intervalo v6.0 (antigo TPO). Distribuição de negócios por níveis de preço em um determinado intervalo de tempo. Exibido como um histograma.Artigos
Indicador de perfil de mercado
Artyom Trishkin, 2025.07.14 11:49
Neste artigo, consideraremos o indicador Market Profile. Descobriremos o que está por trás desse nome, tentaremos entender seus princípios de operação e daremos uma olhada em sua versão terminal (MarketProfile).