Você está na página 1de 60

Estudo de um setup com gaps e HiLo para o Índice no gráfico de 30’

Autores:
Eduardo Sanches (longwave) - eduardo@sanches.odo.br
Isac Costa – isac.costa@gmail.com

Data: Agosto de 2008

Índice

1. Introdução ..................................................................................................................................................... 3
1.1. Motivação................................................................................................................................................ 3
1.2. Sobre este estudo ................................................................................................................................... 4
1.3. Resultado de operações em contratos futuros de Índice Ibovespa.......................................................... 4
1.4. Produção de renda e geração de riqueza ............................................................................................... 5
2. HiLo Activator ................................................................................................................................................ 7
2.1. Definição e Fórmula ................................................................................................................................ 7
2.2. Uso do HiLo Activator como estratégia de stop móvel............................................................................. 8
2.3. Visualização alternativa do HiLo Activator............................................................................................... 9
3. Setup: Gaps com HiLo................................................................................................................................. 12
3.1. Periodicidade ........................................................................................................................................ 12
3.2. Layout Gráfico....................................................................................................................................... 12
3.3. Análise Prévia ....................................................................................................................................... 13
3.4. Sinal de entrada e Stop Inicial............................................................................................................... 13
3.4.1. Gap sem inversão do HiLo ......................................................................................................... 13
3.4.2. Gaps com inversão do HiLo ....................................................................................................... 19
3.5. Considerações sobre a saída do trade.................................................................................................. 24
3.5.1. HiLo Activator ............................................................................................................................. 24
3.5.2. MM10 ......................................................................................................................................... 24
3.5.3. Stop gain pré-definido ou em níveis extremos ............................................................................ 25
3.5.4. Envelopes de Volatilidade .......................................................................................................... 26
3.6. Discussões............................................................................................................................................ 27
3.6.1. Considerações gerais sobre os testes........................................................................................ 28
3.6.2. Testes para Gap sem Inversão do HiLo ..................................................................................... 29
3.6.3. Testes para Gap com Inversão do HiLo ..................................................................................... 33
3.6.4. Gaps com HiLo........................................................................................................................... 34
3.6.5. Estratégia combinada com Slippage e Manejo de Risco ............................................................ 37
4. Considerações finais ................................................................................................................................... 41
5. Referências ................................................................................................................................................. 42
6. Código fonte dos indicadores e explorações para MetaStock...................................................................... 43
6.1. HiLoZone .............................................................................................................................................. 43
6.2. Longwave 1........................................................................................................................................... 43
6.3. Longwave 2........................................................................................................................................... 43
6.4. Exploração “Sim – longwave 12”........................................................................................................... 44
6.5. Longwave 3........................................................................................................................................... 45
6.6. Longwave 4........................................................................................................................................... 45
6.7. Exploração “Sim – longwave 34”........................................................................................................... 46
6.8. Longwave 5........................................................................................................................................... 46
6.9. Longwave 6........................................................................................................................................... 46
6.10. Exploração “Sim – longwave 56” ......................................................................................................... 47
6.11. Exploração “Sim – GapHiLo”............................................................................................................... 47
6.12. Exploração “Sim – Gap HiLo(S)” ......................................................................................................... 48
7. Ferramentas e dados utilizados nos testes.................................................................................................. 49
8. Registro dos trades simulados para cada setup .......................................................................................... 50
9. Código Fonte da DLL TestHelper ................................................................................................................ 50
1
AVISO IMPORTANTE
Este artigo é de autoria de Eduardo Sanches e Isac Costa. Pedimos que sua distribuição não seja realizada
sem um prévio contato com os autores.

As informações deste estudo possuem cunho didático, e baseiam-se em uma análise de operações simuladas
sobre dados históricos em um derivativo, o mini-contrato futuro de Índice Ibovespa, negociado na Bolsa de
Mercadorias e Futuros de São Paulo (BM&F). Estratégias que utilizam derivativos podem resultar em perdas
patrimoniais significativas, por esta razão, recomendamos fortemente que os leitores realizem seus próprios
testes, seja repetindo as simulações aqui realizadas ou através de “paper trading” ou qualquer outro método,
antes de aplicar os setups discutidos em operações reais.

Rentabilidade obtida no passado não representa garantia de rentabilidade futura. Quaisquer rentabilidades
apresentadas aqui são resultados obtidos através de simulações sobre dados históricos.

Desta forma, os autores eximem-se da responsabilidade de quaisquer decisões de investimento tomadas


pelos leitores, ainda que baseadas no conteúdo deste estudo.

Ressaltamos ainda que não há, por parte dos autores, a obrigação em oferecer suporte ou esclarecimentos
sobre quaisquer dúvidas sobre este estudo, ainda que os mesmos possam ser encontrados nos endereços de
e-mail indicados.

Este estudo não é objeto de nenhuma transação comercial entre os autores e os sites onde foram publicados,
representando um esforço voluntário e não remunerado dos mesmos, com o objetivo de compartilhar
conhecimento sobre os mercados e técnicas de trading. Pedimos que, quando da utilização de qualquer
indicador, explorer ou DLL produzido e apresentado aqui, o trabalho dos autores seja devidamente
reconhecido.

2
1. Introdução

1.1. Motivação

Ao considerarmos a variação do mercado como um todo em um determinado período de tempo, usualmente


verificamos a variação percentual do índice que o representa, assim como a taxa de juros livre de risco
(geralmente o CDI acumulado no período).

Entre 3 de Julho de 2006 e 1 de Julho de 2008 (498 dias úteis), o CDI acumulado foi de 25,79%
(http://www.cetip.com.br) e o mini-contrato futuro de Índice Ibovespa variou 20.827 pontos (64.100 – 43.273),
ou 48%. A base de dados do índice futuro utilizada neste estudo foi a série histórica fornecida pela Nelogica
(http://www.nelogica.com.br) em seu software, ProfitChart. Para o mesmo período a variação do Índice
Bovespa foi de 26.768 pontos (63.396 – 36.628) ou 73%.

Ao pensarmos em utilizar uma técnica individual de trading ou um conjunto de técnicas, devemos nos
perguntar se o resultado esperado foi superior à rentabilidade dos índices de referência no período, o que
corresponderia a uma estratégia de “buy and hold” nestes índices. Exemplos destas operações “mais fáceis”
seriam: posição comprada no contrato de índice futuro, rolando para frente a cada novo vencimento, ou
posição em um fundo de renda fixa com rentabilidade o mais próxima possível do CDI ou montagem de uma
carteira com correlação perfeita com o Índice Bovespa.

Será que o método que estamos utilizando supera tais rentabilidades? Será que vale a pena o esforço de
acompanhar o mercado diariamente, conviver com o desgaste psicoló(futo )5s5dasware,ou

3
1.2. Sobre este estudo

Este texto apresenta sugestões de técnicas para a realização de day trades nos mini-contratos futuros de
Índice Ibovespa, em gráficos de 30 minutos. Utilizaremos os termos técnica e setup indistintamente.

Na seção “ferramentas e dados utilizados nos testes”, no final deste texto, apresentamos os softwares
utilizados para as simulações, bem como informações adicionais sobre os dados sobre os quais os testes
foram realizados.

Uma das diretrizes básicas de se fazer backtests sobre dados históricos é sempre desconfiar de resultados
muito bons. Por isso, é sempre bom inspecionar os trades gerados pelo sistema, para verificar se os valores
são realísticos e passíveis de execução. Por esta razão, incluímos na seção “Registro dos trades realizados
para cada setup” uma tabela contendo os trades registrados pela programação dos setups e seus valores de
entrada e saída, para inspeção manual dos leitores.

As operações de índice são diferentes das operações com ações em muitos aspectos, porém as técnicas
apresentadas aqui não se restringem apenas ao índice. Foi uma escolha pessoal dos autores o uso do índice
futuro, pelas seguintes razões:

 Facilidade de comparação dos resultados dos trades com o rendimento do próprio índice no período de
análise e com o risco de mercado (representado pelo próprio índice)
 Eliminação do processo de seleção de ativos – em se tratando de day trades, vários autores recomendam
a especialização do trader em poucos ativos ou até mesmo em um único ativo.
 Podemos medir os resultados - lucro e drawdown - de cada setup em pontos ao invés de percentuais.
Esta é uma abordagem mais flexível para determinar o tamanho das posições que iremos utilizar,
permitindo um ajuste fino do nível de alavancagem que desejamos.

Buscamos apresentar as técnicas visando diminuir a subjetividade na tomada de decisão. Para cada técnica
são discutidos:

 Periodicidade: prazo operacional para as operações


 Layout gráfico: tipo de gráfico e indicadores a serem inseridos e configurados
 Análise prévia: critérios gerais a serem observados antes da execução dos trades
 Sinal de entrada: critérios gráficos para a entrada em um trade, tamanho da posição e stop inicial
 Sinal de saída: critérios gráficos para a finalização de uma posição
 Discussões: resultados sobre dados históricos, limitações e comentários gerais sobre sua utilização

As técnicas aqui apresentadas são conjecturas dos autores feitas a partir de sua própria experiência e da
experiência de outros traders com os quais estivemos em contato nos últimos dois anos. A contribuição de
outros autores e destes traders será devidamente reconhecida em cada caso.

1.3. Resultado de operações em contratos futuros de Índice Ibovespa

A especificação dos mini-contratos futuros de Índice Ibovespa pode ser encontrada em:

http://www.bmf.com.br/portal/pages/frame_home.asp?idioma=1&link=/portal/pages/webtrading1/pdf/contrato_i
bovespa.pdf

Esta especificação foi alterada pelo Ofício Circular 038/2006-DG, de 30/03/2006:

http://www.bmf.com.br/portal/pages/frame_home.asp?idioma=1&link=/portal/pages/boletim1/informes/2006/ma
rco/OC038-2006.pdf
4
De forma resumida, o resultado financeiro de uma operação em mini-índice pode ser calculado por:

Resultado = Quantidade x (Valor Final – Valor Inicial) / 5

Para operações de compra, a quantidade é positiva e para operações de venda, a quantidade é negativa. Os
valores inicial e final representam, respectivamente, os valores de negociação na abertura e no encerramento
da posição.

Assim, um indivíduo que abrir uma posição de compra de 8 mini-contratos a 67.000 pontos e encerrar esta
posição a 67.350 pontos terá um resultado de:

Resultado = 8 x (67.350-67.000) / 5 = 560 reais (Lucro)

Se outro indivíduo abrir uma posição de venda de 13 mini-contratos a 67.000 pontos e encerrar esta posição a
67.350 pontos terá um resultado de:

Resultado = - 13 x (67.350-67.000) / 5 = - 910 (Prejuízo)

Se fizermos com que os tamanhos das posições sejam múltiplos de 5, o cálculo fica mais fácil de ser
executado. Para cada 5 mini-contratos, o número de pontos da operação equivale ao resultado financeiro.
Dessa forma, poderemos ver, de forma idêntica, qual o número líquido de pontos e reais fornecido por cada
técnica em um determinado período.

1.4. Produção de renda e geração de riqueza

Antes de prosseguirmos na análise da rentabilidade sobre a margem em operações com índice, vale a pena
mencionar uma distinção feita por Oliver Velez, em seu livro “Tools and Tactics for the Master Day Trader” e
em seus diversos vídeos. Para Velez, há duas formas de se abordar estratégias de trading: obter uma renda
constante do mercado ou aumentar o seu patrimônio.

No primeiro caso, quando estamos interessados em produção de renda (income producing), tentamos
encontrar métodos de alta confiabilidade que permitam que, a cada pregão, tenhamos uma rentabilidade que,
mesmo que pequena, se obtida constantemente, irá produzir uma renda mensal em conformidade com metas
pré-estabelecidas. Muitos os que se aventuram como day traders, buscam este tipo de rentabilidade.

A alternativa consiste em aumentar o patrimônio gradualmente, com uma mentalidade de “investidor” na qual
os resultados individuais não são tão relevantes - pode-se fechar um mês no negativo, por exemplo – mas o
que importa é a rentabilidade em um prazo maior (ex. anual,) visando se beneficiar do efeito dos juros
compostos. Exemplos deste tipo de estratégia, mais confiável em períodos de forte tendência nos mercados,
são estratégias de “position trading” e “buy and hold” com ou sem lançamentos cobertos ou outras técnicas de
se remunerar carteiras.

Dito isso, veremos que, pelo menos em teoria, é possível buscar uma abordagem no estilo “income producing”
para operações com o índice futuro.

Cada corretora exige uma margem inicial e uma margem de manutenção para a abertura de posições de mini-
índice. Assumiremos que este valor é igual a R$ 2.000,00 para cada mini-contrato. Desta forma, as margens
requeridas para as operações acima mencionadas seriam, respectivamente, R$ 16.000,00 (para 8 minis) e R$
26.000,00 (para 13 minis), e os resultados percentuais sobre as margens seriam de +3,5% (560/16.000) e -
3,5% (910/26.000).

Perceba que, em ambos os casos, o índice variou aproximadamente 0,5% (350 / 67.000), mas os resultados
financeiros foram potencializados pela alavancagem oferecida por este instrumento. Esta característica pode
5
amplificar tanto os ganhos quanto as perdas, e é um dos principais fatores que atraem especuladores – em
especial day traders - para derivativos.

Se considerarmos uma estratégia que propicie um resultado líquido de 100 pontos por pregão e
considerarmos que estaremos atuando em 10 pregões em cada mês, teríamos um resultado de 1.000 pontos
no mês. Se mantivermos uma conta margem com saldo de R$ 20.000,00 e operarmos posições constantes de
5 mini-contratos, utilizando R$ 10.000,00 para margem e o restante como reserva de segurança para trades
negativos, teríamos um resultado financeiro de R$ 1.000,00 sobre os R$ 20.000,00, um percentual de 5%
sobre a margem no período em questão.

Desta forma, estamos interessados em técnicas cujos resultados sejam médias constantes e positivas para
cada pregão e façam com que o capital não seja depreciado a ponto de não permitir ao menos a abertura da
posição mínima. No exemplo anterior, se tivermos perdas consecutivas que façam com que o capital caia
abaixo de R$ 10.000,00 não poderemos abrir a posição constante de 5 mini-contratos.

Em termos técnicos, estaremos interessados em setups que gerem resultados líquidos de, ao menos 100
pontos por trade e que tenham um drawdown máximo que fique o mais longe possível de 20% sobre o capital
inicial em cada período. Veja que não necessariamente buscamos setups com mais de 70 ou 80% de acertos,
mas sim aqueles cuja diferença entre o resultado médio dos trades positivos e o resultado médio dos trades
negativos seja positiva e superior a 100 pontos.

Uma limitação prática desta abordagem consiste no fato de que, após uma seqüência de trades negativos,
mesmo que com pequenas perdas, o operador pode “perder a confiança” no seu método e abandoná-lo,
justamente antes da realização do trade positivo que compensaria todas as perdas anteriores e geraria lucro.
Outra limitação é representada pelo fato de que operadores humanos não necessariamente irão executar
todos os sinais fornecidos por um setup, havendo o risco de que trades vitoriosos sejam perdidos e os lucros
potenciais não sejam realizados.

Uma observação importante

Embora a alavancagem proporcionada pelo mini-índice permita estes ganhos potenciais consideráveis, a não
perfeita execução das técnicas, o fator probabilístico das mesmas e as diversas barreiras psicológicas
enfrentadas pela maioria dos participantes dos mercados impedem que estes resultados potenciais sejam
efetivamente realizados.

O objetivo deste artigo não é iniciar uma cruzada pelo “Santo Graal” dos trades, mas sim discutir métodos que
possam ser executados quase que de uma forma algorítmica, que sejam de visualização e execução
relativamente simples e que se encaixem nos requisitos de performance mencionados anteriormente.

6
2. HiLo Activator
2.1. Definição e Fórmula

Nesta seção apresentamos o HiLo Activator, um dos indicadores fundamentais para os setups analisados
neste artigo. O HiLo Activator, também conhecido como Gann HiLo Activator ou simplesmente HiLo, foi
apresentado pela primeira vez por Robert Krausz em um artigo publicado na revista Stocks & Commodities
em Fevereiro de 1998 denominado “The New Gann Swing Chartist”. O conteúdo deste artigo foi publicado
novamente no “The Fibonacci Trader Journal” e seu conteúdo está disponível online (vide seção
“Referências”).

Em geral, as médias móveis utilizam preços de fechamento em seu cálculo. A proposta do HiLo Activator, ao
qual nos referenciaremos a partir daqui simplesmente por HiLo, consiste em observar duas médias móveis, a
das máximas e a das mínimas dos N períodos anteriores, com deslocamento de 1 período. Caso o
fechamento tenha ocorrido acima da média das máximas, entramos em uma zona “positiva” ou “comprada”.
Caso o fechamento ocorra abaixo da média das mínimas, temos a zona inversa, “negativa” ou “vendida”.
Caso estejamos “comprados”, os valores da média das mínimas representam patamares que, se perdidos,
indicam fraqueza no movimento, representando, dessa forma, pontos de saída do trade. No caso de estarmos
“vendidos”, a média das máximas representa um ponto de referência para saída do trade, de forma análoga.

Um cuidado especial: a média com a qual comparamos o valor de fechamento do candle é a média de
máximas e mínimas dos N períodos anteriores. Nos softwares gráficos em geral, o valor de qualquer média
móvel inclui para um determinado candle inclui os valores deste candle em seu cálculo. No caso do HiLo,
devemos utilizar a MM fornecida pelo software para o período anterior, desta forma, já teremos os dois valores
que irão servir de referência antes que o candle seja formado.

Figura 2.1. HiLo Activator no gráfico diário da série histórica do mini-índice

7
Os valores das médias móveis são desenhados de forma pouco usual, como patamares, conectados a cada
dia, criando a impressão de estarmos vendo uma “escada” ascendente ou descendente de stops móveis. Na
figura, as linhas em vermelho representam stop loss de compra (zona comprada) e as verdes representam
stop loss de venda (zona vendida). Perceba que, quando um candle perde (ou rompe) o patamar definido pelo
HiLo do período anterior, temos um possível ponto de saída do trade.

Em geral, utiliza-se o HiLo de 3 períodos, isto é, as médias móveis de máximas e mínimas são médias móveis
aritméticas de 3 períodos. Nos setups apresentados neste artigo, porém, utilizaremos HiLos de períodos
alternativos, como o de 10 períodos.

No software Metastock, da Equis International o HiLo pode ser criado como um indicador personalizado,
utilizando-se a seguinte fórmula:

period:=Input("Period",1,100,3);
MovH:=Ref(Mov(H,period,S),-1);
MovL:=Ref(Mov(L,period,S),-1);
HLd:=If(C>MovH,1,If(C<MovL,-1,0));
HLv:=ValueWhen(1,HLd<>0,HLd);
HiLo:=If(HLv=-1,MovH,MovL);
HiLo;

Porém, a visualização é ligeiramente diferente da indicada na Figura 2.1, não ficando claras as zonas
compradas e vendidas como no software ProfitChart, da Nelogica. Por esta razão, criamos um indicador
chamado HiLoZone para o Metastock, que será utilizado nas simulações.

period:=Input("Period",1,100,10);
MovH:=Ref(Mov(H,period,S),-1);
MovL:=Ref(Mov(L,period,S),-1);
HLd:=If(C>MovH,1,If(C<MovL,-1,0));
HLv:=ValueWhen(1,HLd<>0,HLd);
HiLoZone:=If(HLv=-1,-1,1);
Change:=If(HiLoZone<>Ref(HiLoZone,-1),1,0);
BullishChange:=Change AND HiLoZone=1;
BearishChange:=Change AND HiLoZone=-1;
HiLoZone;

2.2. Uso do HiLo Activator como estratégia de stop móvel

Devido a própria forma de construção do HiLo, o indicador nasceu naturalmente para ser um stop móvel, seja
de uma posição comprada ou de uma posição vendida. Em tendências fortes, o HiLo mostra-se um
sinalizador eficaz de pontos de realização de lucros. Como trata-se de um indicador que utiliza médias móveis
em seu cálculo, o HiLo também apresenta as mesmas limitações do uso de médias, em particular a ineficácia
de seus sinais em períodos de congestão, alternando rapidamente entre as zonas compradas e vendidas. A
figura a seguir mostra esta situação em um gráfico semanal da série histórica do mini-índice.

As linhas inclinadas em amarelo indicam períodos de forte tendência nas quais os stops móveis de venda não
foram acionados. No momento em que foram acionados, representaram pontos interessantes de realização
de lucros. O retângulo indicado mostra um período de mercado lateral, onde os sinais do HiLo Activator
invertem-se rapidamente e também as médias móveis (não indicadas na figura) refletem a indefinição do
mercado.

8
Figura 2.2. HiLo no gráfico semanal do mini-índice

Indicadores semelhantes ao HiLo quanto ao uso (stop móvel) são o VSS, criado por Joe Ross, e o SAR
parabólico, criado por Welles Wilder.

2.3. Visualização alternativa do HiLo Activator

Para softwares de cotações que não permitam a criação de indicadores personalizados, uma alternativa de
visualização do HiLo consiste em desenhar as médias móveis das máximas e das mínimas. Em geral é
possível especificar qual o preço que uma média móvel irá utilizar, o padrão é o preço de fechamento, mas
abertura, máxima e mínima também podem ser utilizados.

No ProfitChart, da Nelogica, ao inserir uma média móvel no gráfico é possível especificar o valor a ser
utilizado conforme a figura a seguir, além de especificar um deslocamento de 1 período, para que o valor das
médias de referência para o candle atual não utilize os valores ainda em formação.

A “virada” do HiLo ocorrer sempre que houver um fechamento acima da média móvel das máximas (HiLo
passa ou continua a ser comprado) ou um fechamento abaixo da média móvel das mínimas (HiLo passa ou
continua a ser vendido). Eventualmente, os setups podem envolver apenas uma penetração de uma destas
médias, o que pode ser observado apenas nesta forma de visualização.

9
Figura 2.3.1 Especificando a média das máximas e das mínimas no ProfitChart®

Figura 2.3.2 Visualização do HiLo como médias móveis de máximas e mínimas

Observe o efeito resultante na Figura 2.3.2. Cria-se um envelope com as duas médias e os rompimentos
destes envelopes indicam sinais de compra ou venda, sejam estes sinais que iniciem um trade ou sinais de
stop para posições originalmente inversas. Em gráficos intraday, onde há uma maior variação nas tendências
dos preços do que em gráficos de periodicidade maior, a visualização do HiLo como médias permite uma
10
técnica interessante, embora fora do escopo deste artigo. Sugerimos ao leitor que tente observar
empiricamente as regras de trading que podem ser criadas com o indicador configurado desta forma e que
também insira o HiLo Activator no mesmo gráfico para verificar a conformidade dos valores com as médias
móveis e a mudança de zona cada vez que o fechamento fecha fora do envelope de médias.

A sugestão da visualização do HiLo como médias foi uma idéia do trader Roger Batté, também conhecido
como Frances. Nas seções a seguir iremos analisar o uso do HiLo com outros padrões gráficos para definição
de critérios de entrada e saída de trades.

11
3. Setup: Gaps com HiLo
3.1. Periodicidade

Este é um setup que explora gaps no índice, orientando as ações através de uma média móvel de referência
e sinais de fraqueza ou força determinados pelo HiLo Activator e por um range inicial de duas horas de
duração. O setup considera o gráfico de 30 minutos do índice.

3.2. Layout Gráfico

O layout para análise consiste nos seguintes indicadores:

 Gráfico de candlestick de preços 30 minutos


 HiLo Activator de 10 períodos (ou média móvel de máximas e mínimas de 10 períodos com 1 de
deslocamento)
 Média móvel aritmética de 10 períodos
 Volume financeiro (com média de referência)

Figura 3.2.1 Layout para análise

12
3.3. Análise Prévia

Assumiremos que o leitor é familiarizado com o conceito de gap e os termos “gap aberto” e “fechamento de
gap”. Uma das características fundamentais do gráfico do contrato futuro de índice Ibovespa é a presença
constante de gaps entre dois dias distintos.

A observação da tendência dos dias anteriores e se a direção do gap é a favor ou contra esta tendência pode
nos indicar uma probabilidade de o gap ser ou não fechado. Sem entrar em detalhes específicos sobre estudo
de gaps, as informações que consideramos relevantes são:

 Gaps de alta seguidos de dias de alta e gaps de baixa seguidos de dias de baixa – denominados “gaps
amadores” têm MAIOR probabilidade de serem fechados.
 Gaps de alta após dias seguidos de baixa e gaps de baixa após dias seguidos de alta – denominados
gaps profissionais – têm MENOR probabilidade de serem fechados.
 Gaps abertos comumente servem como importantes zonas de suporte e resistência.

Os conceitos de gap de área, exaustão, medida e fuga podem ser aplicados, desde que seja analisada sua
posição dentro da tendência descrita no gráfico de 30 minutos. A técnica proposta aqui, porém, não se baseia
nas táticas comuns de se operarem este tipo de gap. Recomendamos aos leitores uma pesquisa adicional
sobre o assunto, visando apenas, no escopo do setup descrito aqui, determinar se há uma probabilidade
maior ou menor de o gap ser fechado.

Nos testes sobre dados históricos, não consideramos o tipo de gap e a efetivação do trade ou não conforme o
resultado desta análise. Acreditamos que este pode ser um filtro adicional a ser aplicado pelo trader quando
da utilização manual do setup.

3.4. Sinal de entrada e Stop Inicial

3.4.1. Gap sem inversão do HiLo

Teremos uma entrada na ponta de COMPRA se:

a) Houver um gap de alta (superior a 200 pontos)


b) O HiLo Activator(10) estiver sempre comprado, desde a abertura
c) A mínima do dia estiver no máximo 100 pontos acima do fechamento do dia anterior
d) Ocorrer o rompimento da máxima dos primeiros quatro candles (primeiras duas horas de pregão)
e) Não ter ocorrido um sinal de compra no mesmo dia (apenas 1 trade por dia)

Caso estas condições sejam satisfeitas, entramos no rompimento da máxima dos primeiros quatro candles,
sem esperar fechamento, com stop inicial abaixo da mínima do candle que originou a entrada. A saída do
trade ocorrerá se houver um fechamento abaixo da média móvel simples de 10 períodos das mínimas, OU em
stop gain ou perda máxima (veja comentários a seguir) OU no final do dia. O fechamento abaixo da MM10 das
mínimas equivale a uma mudança de zona de HiLo comprado para HiLo vendido. Na ponta comprada, testes
realizados indicaram que o uso da lógica de stop gain ou perda máxima não melhorou a performance
significativamente.

Teremos uma entrada na ponta de VENDA se:

a) Houver um gap de baixa (superior a 200 pontos)


b) O HiLo Activator(10) estiver sempre vendido
c) A máxima do dia estiver no máximo 100 pontos abaixo do fechamento do dia anterior
d) Ocorrer a perda da mínima dos primeiros quatro candles (primeiras duas horas de pregão)

13
e) Não ter ocorrido um sinal de compra no mesmo dia (apenas 1 trade por dia)

Na presença destas condições, a entrada ocorre na perda da mínima dos primeiros quatro candles, sem
esperar fechamento, com stop inicial acima da máxima do candle que originou a entrada. A saída do trade
ocorrerá se houver um fechamento acima da média móvel simples de 10 períodos das máximas, OU em stop
gain ou perda máxima OU no final do dia. O fechamento acima da MM10 das máximas equivale a uma
mudança de zona do HiLo vendido para HiLo comprado. Na ponta vendida, o uso de um stop gain de 700
pontos mostrou-se capaz de melhorar os resultados do setup.

Como funciona a lógica do stop gain e da perda máxima? Na ausência de gaps, se o resultado do trade atinge
o valor de perda máxima ou stop gain, o trade é finalizado imediatamente. Por exemplo, se uma compra se
deu em 65.000 e o stop gain é de 500 pontos, assim que os preços atingirem 65.500, o trade é finalizado.
Porém, havendo um gap, se o novo candle abre acima de 65.500, suponhamos 65.800, saímos no preço de
abertura deste candle. O raciocínio para a perda máxima é análogo. A principal diferença é que quando os
preços andam contra a entrada já na mesma barra um valor superior à perda máxima, a saída ocorre na
abertura do candle seguinte.

Para programar esta e outras lógicas adicionais, criamos uma DLL para o Metastock, utilizando o Metastock
Developer’s Kit, denominada TestHelper.DLL. Disponibilizamos no final deste documento o código fonte desta
DLL para que a lógica de stop gain e perda máxima seja visualizadas. Veja também a seção “Ferramentas e
dados utilizados nos testes” para maiores informações.

Vamos analisar alguns exemplos para os casos descritos aqui. Observe que estes exemplos são meramente
ilustrativos e não há garantia alguma de que o mercado se comportará desta forma sempre. Ao aplicarmos o
setup, estamos fazendo uma aposta de que o comportamento dos preços será semelhante, devido à
preservação do momentum de um dia para o outro e a confirmação deste fato via HiLo Activator, não violação
do gap e/ou e rompimento de range.

14
Exemplo 3.4.1.1 – Operação bem-sucedida de gap de alta com HiLo comprado

Observe a entrada no rompimento do range, o stop móvel da MM10 das mínimas e a saída no final do pregão,
devido ao fato de o stop não ter sido acionado. Esta seria uma configuração perfeita do setup na ponta
comprada. Vejamos um exemplo de uma operação mal-sucedida com este setup.

15
Exemplo 3.4.1.2 – Operação mal-sucedida de gap de alta com HiLo comprado

Veja a entrada no rompimento do range dos primeiros quatro candles. Infelizmente o setup gerou uma entrada
próxima à máxima do dia, e os preços recuaram até que ocorreu um fechamento abaixo da média móvel das
mínimas, resultando em uma perda de pouco mais de 300 pontos. Caso o fechamento ocorresse abaixo do
stop inicial, este deveria ser usado como preço de saída (mínima do candle que iniciou a entrada menos 200
pontos).

Uma observação importante: sabemos que o valor mínimo de variação do contrato futuro de índice é de 5
pontos, porém veremos em algumas figuras e no próprio resultado da simulação, valores tais como 65.733 ou
55.418. Isto se deve ao fato de que a série histórica fornecida pelo ProfitChart realiza ajustes a cada
vencimento, a fim de normalizar os valores de contratos de diferentes vencimentos.

Vejamos agora exemplos na ponta vendida.

16
Exemplo 3.4.1.3 – Operação bem-sucedida de gap de baixa com HiLo vendido

Teria sido a saída no stop gain precoce? Vemos que, para este trade, o mercado andou um pouco mais.
Porém, veremos que, estatisticamente, a presença de stop gain para trades na ponta vendida melhora
drasticamente a performance. Fica a critério do leitor o desenvolvimento de estratégias de saída alternativas
às aqui apresentadas.

No próximo exemplo, veremos uma operação mal-sucedida com este setup. O ponto de venda foi próximo à
mínima do dia, e os preços andaram contra o trade até que ocorreu um fechamento acima da média móvel de
10 períodos das máximas, resultando em uma perda de cerca de 780 pontos.

17
Exemplo 3.4.1.4 – Operação mal-sucedida de gap de baixa com HiLo vendido

Achamos fundamental mostrar exemplos de situações nas quais o setup falhou. Vemos em muitos livros,
apenas exemplos bem escolhidos de situações nas quais o setup em discussão fez um trade perfeito, o que
geralmente induz os leitores a acreditarem em técnicas milagrosas, dada sua tradicional assimetria de
expectativas entre ganhos e perdas e a “lei dos pequenos números”. Na opinião dos autores, este tipo de
conduta não contribui para a reputação dos analistas técnicos que, infelizmente, são colocados no mesmo
nível que vendedores de idéias de ganhos fáceis nos mercados de renda variável.

Perceba que neste setup não estamos operando contra o gap, mas sim fazendo uma aposta direcional
definida pela permanência da zona do HiLo e a não violação do gap, seguida ou não de rompimento a favor
da direção do mesmo.

Vamos agora analisar uma situação um pouco diferente, na qual ocorre uma mudança de zona do HiLo,
sinalizando que a direção do movimento anterior poderá ser invertida.

18
3.4.2. Gaps com inversão do HiLo

As condições para COMPRA são:

a) Gap de baixa (acima de 200 pontos)


b) Mudança de zona do HiLo de vendido para comprado (ou penetração de preço acima da média móvel
das máximas de 10 períodos)
c) Preços andando na máxima do dia

Stop inicial 200 pontos abaixo da mínima do candle que gerou a entrada. Saída quando fechar abaixo do stop
inicial OU fechar abaixo da média das mínimas de 10 períodos (= inverter o HiLo) OU no final do dia. Nos
testes realizados, um dos melhores resultados foi obtido utilizando-se um stop gain de 500 pontos e uma
perda máxima de 300 pontos.

As condições para VENDA são:

a) Gap de alta (acima de 200 pontos)


b) Mudança de zona do HiLo de comprado para vendido (ou penetração de preço abaixo da média móvel
das mínimas de 10 períodos)
c) Preços andando na mínima do dia

Stop inicial 200 pontos acima da máxima do candle que gerou a entrada. Saída quando fechar abaixo do stop
inicial OU fechar acima da média das mínimas de 10 períodos (=inverter o HiLo) OU no final do dia. Para a
ponta vendida, o critério de perda máxima de 400 pontos e saída via stop gain conforme regra a seguir
apresentou o melhor resultado dentre os diversos testados. O stop gain ocorrer no fechamento do candle no
qual ocorrerem os seguintes fatores:

a) Lucro do trade estiver acima de 300 pontos


b) Máxima do candle for menor que a máxima do candle anterior

A lógica por trás desta regra consiste no fato de que o mercado geralmente cai mais rápido do que sobe e a
idéia é tirar proveito de barras negativas longas que ocorram logo após a entrada do trade, evitando ficar
posicionado depois de um repique nos preços. Se o leitor observar a lista de trades no final deste documento
irá verificar as boas saídas geradas através deste critério.

Devemos tomar um cuidado especial aqui no que diz respeito à mudança de zona do HiLo. Ela dependerá do
fato de o fechamento do candle ser superior à média móvel das máximas ou inferior à média móvel das
mínimas. Em um candle em formação, o HiLo pode mudar de zona, dependendo do preço atual. Temos duas
alternativas: podemos considerar uma violação de uma destas médias móveis para iniciar o trade OU
podemos esperar o fechamento para nos certificar sobre qual é a zona do HiLo. Nos testes realizados, a
primeira alternativa apresentou melhores resultados.

19
Exemplo 3.4.2.1 – Operação bem-sucedida de gap de alta e reversão do HiLo de compra para venda

A entrada se deu na penetração dos preços na média móvel das mínimas de 10 períodos, sendo que ali os
preços estavam trabalhando na mínima do dia. A saída se deu no fechamento do candle cuja mínima foi
menor que a mínima anterior e o lucro apurado (entrada – fechamento) foi superior a 300 pontos.

20
Exemplo 3.4.2.2 – Operação mal-sucedida de gap de alta e reversão do HiLo de compra para venda

A entrada se deu apenas quando a mínima do dia foi perdida. A saída ocorreu quando houve um repique de
400 pontos a partir do ponto de entrada, na perda máxima.

21
Exemplo 3.4.2.3 – Operação bem-sucedida de gap de baixa e reversão do HiLo de venda para compra

A entrada ocorreu na penetração da média móvel das máximas de 10 períodos e a saída via stop gain de 500
pontos.

22
Exemplo 3.4.2.4 – Operação mal-sucedida de gap de baixa e reversão do HiLo de venda para compra

Aqui, a entrada se deu no rompimento da média móvel das máximas de 10 períodos. A saída se deu na perda
máxima, programada em 300 pontos, alguns candles depois.

Uma vez apresentados os setups, vamos discutir brevemente sobre as diversas alternativas de critérios de
saída e, posteriormente, apresentar os resultados obtidos para a programação das regras aqui discutidas
sobre uma base de dados de 2 anos da série histórica de mini-contratos futuros de Índice Ibovespa.

23
3.5. Considerações sobre a saída do trade

Já mencionamos que a saída de um trade é mais relevante do que a entrada, no tocante à determinação do
lucro ou prejuízo da operação. Esta é uma idéia defendida exaustivamente pelo Prof. Van Tharp em seu livro
“Trade Your Way To Financial Freedom”.

Para quaisquer setups, podemos ter vários critérios de saída, dentre os quais:

 Stop móvel via HiLo Activator (gera stop se, por exemplo, estamos comprados e a média móvel das
máximas ou mínimas é violada)
 Fechamento de candle abaixo de uma média de referência (ex. MM10)
 Stop gain pré-definido em pontos ou em níveis extremos como os pontos R2 e S2 do ponto de pivô
intradiário ou somando-se e subtraindo-se 1 True Range ao preço de abertura
 Uso de envelope de volatilidade (ex. Banda de Bollinger, somando-se 2 desvios padrões à media, ou um
envelope de ATR, somando-se 2 ou 3 ATRs de 10 períodos à média).

Vamos analisar cada uma destas opções. O mais importante é que existe um trade-off entre permanecer mais
tempo no trade para tentar obter o máximo do movimento, com uma maior exposição a inversões na sua
direção versus sair rapidamente e garantir o lucro o mais rápido possível, abrindo mão de ganhos adicionais.
Vale lembrar que estamos falando de day trading, portanto não estamos interessados em carregar posições
de um dia para outro e temos apenas 16 candles para cada pregão em um gráfico de 30 minutos. Cada um
deve encontrar o ponto com o qual se sente mais à vontade para sair do trade, porém cada escolha irá
impactar significativamente na rentabilidade do sistema ao longo do tempo.

3.5.1. HiLo Activator

Já discutimos brevemente sobre o uso do HiLo Activator como stop móvel. Como estamos utilizando o
HiLo(10) em gráficos de 30 minutos, observamos que a distância mínima do HiLo ao fechamento de um
candle com estas configurações dificilmente chega a menos que 400 pontos. Isto quer dizer que quando
estamos em uma tendência forte e utilizamos o HiLo como stop é bem provável que deixaremos pelo menos
400 pontos para o mercado. O problema maior deste sistema de stop não ocorre em situações de tendência
forte, mas sim quando as coisas dão errado. Observando o gráfico do índice, podemos ver vários exemplos
nos quais o movimento chegou a andar um número considerável de pontos a favor da entrada, digamos 1 ou
até mesmo 2 ATRs, mas o HiLo Activator não subiu o suficiente para proteger os lucros. Por conta destes
casos, somos motivados a pensar em quais alternativas existem para capturar lucros quando ocorre um
movimento favorável imediatamente após a entrada.

3.5.2. MM10

Uma das alternativas seria buscar um indicador que não fique tão afastado dos preços quanto o HiLo(10),
como, por exemplo, a MM10. Em geral a MM10 e o HiLo(10) andam próximos, mas quando o movimento é
acelerado a MM10 oferece uma proteção maior, como mostra a figura a seguir. Durante toda a queda, a
MM10 “deixa menos pontos para o mercado” que o HiLo(10), resultando em um aproveitamento de cerca de
200 pontos. Podemos considerar como stop qualquer fechamento de candle abaixo ou acima da MM10 para
posições compradas e vendidas, respectivamente.

24
Figura 3.5.2.1. HiLo(10) versus MM10 como stop móvel

O problema desta abordagem é que, quanto mais próximos deixamos o stop móvel dos preços atuais, maior a
probabilidade de sermos estopados e deixar o movimento. Há vezes em que estamos mais interessados em
navegar por toda a tendência do que aproveitar cada perna do movimento individualmente. Esta é uma
decisão que depende muito do estilo pessoal de cada trader.

3.5.3. Stop gain pré-definido ou em níveis extremos

Ao fazermos um estudo estatístico de cada trade, poderemos ter uma idéia de até quanto, em média, um
determinado movimento anda a favor ou contra uma entrada executada pelo setup. Podemos, dessa forma,
mover o stop imediatamente para o nível de preços correspondente ao valor de entrada mais um valor
esperado médio, uma vez que este nível seja atingido. Por exemplo, ao descobrirmos que um trade vencedor
costuma andar, em média, 500 pontos a favor da entrada, ao atingirmos este patamar, poderemos
imediatamente subir o stop para a mínima do candle atual (assumimos uma posição comprada) e caso os
preços subam mais, mover para o valor correspondente a entrada + 500 pontos.

Um raciocínio análogo pode ser usado caso os preços cheguem a níveis considerados extremos para um
único pregão. Exemplos de níveis extremos são os pontos S2 e R2 do ponto de pivô intradia. Estes pontos
são definidos como sendo a amplitude do dia anterior (máxima – mínima) projetadas a partir de um ponto de
referência denominado de ponto de pivô. Matematicamente:

25
PP = (High + Low + Close)/3
S2 = PP – (High-Low)
R2 = PP + (High-Low)

Estes níveis usualmente correspondem a máximas e mínimas de um determinado pregão, mas podem ser (e
são) ultrapassados com alguma freqüência. O importante aqui é ter um sentimento de que os preços já
andaram bastante e é melhor ter precaução para proteger os lucros da melhor forma possível.

Uma alternativa para detectar níveis extremos no intraday consiste em adicionar e subtrair 1 True Range ao
preço de abertura. O True Range de um determinado período consiste em somar a amplitude deste período
(máxima – mínima) com um eventual gap do período anterior. Em caso de gap de alta, adicionamos à
amplitude a diferença entre a mínima do período atual e o fechamento anterior. Em caso de gap de baixa,
adicionamos à amplitude a diferença entre o fechamento anterior e a máxima do período atual.

3.5.4. Envelopes de Volatilidade

O mais conhecido envelope de volatilidade são as Bandas de Bollinger, criadas por John Bollinger. Para criá-
las são somados e subtraídos à média móvel de referência (no caso a MM10) dois desvios-padrão, criando,
desta forma, um intervalo de confiança para os preços (95%). Ao atingir a banda superior ou a banda inferior,
podemos dizer que os preços estão chegando a níveis extremos. Porém, simplesmente colocar um stop gain
nas BBs pode levar a saídas precoces, pois em movimentos fortes, elas costumam se “abrir”, aumentando os
limites até onde os quais os preços podem chegar.

Uma estratégia alternativa consiste em utilizar um stop móvel na mínima de cada novo candle que se forme
após um determinado candle ter tocado uma das bandas. Assim, quando ocorrerem movimentos fortes, os
stops conseguem caminhar junto com os preços de forma eficaz e só ocorrerá uma saída do trade uma vez
que uma mínima tenha sido perdida. Utilizar valores de fechamento ou simples penetrações quando o candle
ainda está em formação é uma opção que depende, novamente, do estilo pessoal do trader.

Um outro envelope de volatilidade que podemos utilizar, que move-se mais suavemente que as Bandas de
Bollinger, é um envelope de ATRs, nos quais somamos e subtraímos 3 ATRs à média móvel de referência.
ATR é a abreviatura de Average True Range, um indicador criado por Welles Wilder, que consiste em uma
média móvel do True Range (apresentado na seção anterior). Para as configurações do setup aqui
apresentadas, recomendamos o uso da MM10 e a soma e subtração de 3 ATRs de 10 períodos. Este
indicador não está disponível no ProfitChart, mas pode ser programado para MetaStock, utilizando-se a
seguinte fórmula:

APeriod:=Input("MAPeriod",1,100,20);
ATRPeriod:=Input("ATRPeriod",2,100,10);
ATRFactor:=Input("ATRFactor",0.1,10,3);

MidBand:=Mov(CLOSE,MAPeriod,S);
UpBand:=MidBand + ATRFactor*ATR(ATRPeriod);
LowBand:=MidBand - ATRFactor*ATR(ATRPeriod);

UpBand;
MidBand;
LowBand;

O uso do envelope de ATR foi sugerido pelo trader Rogério Passos, da região de Campinas.

26
3.6. Discussões

Antes de iniciarmos a discussão da validade estatística do setup, apresentamos um breve resumo de tudo o
que foi discutido até aqui:

Análise Prévia  Determinar se o gap em questão possui MAIOR ou MENOR probabilidade de ser FECHADO,
analisando a tendência do gráfico e classificando o tipo de gap.
 Analisar a tendência prévia dos últimos pregões pela posição relativa dos preços e a MM10 e topos
e fundos ascendentes ou descendentes
Gap sem Gap de Alta com HiLo Comprado – COMPRA:
inversão de
HiLo a) Houver um gap de alta (superior a 200 pontos)
b) O HiLo Activator(10) estiver sempre comprado, desde a abertura
c) A mínima do dia estiver no máximo 100 pontos acima do fechamento do dia anterior
d) Ocorrer o rompimento da máxima dos primeiros quatro candles (primeiras duas horas de pregão)
e) Não ter ocorrido um sinal de compra no mesmo dia (apenas 1 trade por dia)

Stop inicial 200 pontos abaixo da mínima do candle que originou a entrada A saída do trade ocorrerá se
houver:

 um fechamento abaixo da média móvel simples de 10 períodos das mínimas


 no final do dia

Gap de Baixa com HiLo Vendido – VENDA:

a) Houver um gap de baixa (superior a 200 pontos)


b) O HiLo Activator(10) estiver sempre vendido
c) A máxima do dia estiver no máximo 100 pontos abaixo do fechamento do dia anterior
d) Ocorrer a perda da mínima dos primeiros quatro candles (primeiras duas horas de pregão)
e) Não ter ocorrido um sinal de compra no mesmo dia (apenas 1 trade por dia)

Stop inicial 200 pontos acima da máxima do candle que originou a entrada A saída do trade ocorrerá se
houver:

 um fechamento acima da média móvel simples de 10 períodos das máximas


 stop gain de 700 pontos
 no final do dia

Gap com Gap de Baixa com Inversão de HiLo para Compra - COMPRA:
inversão de
HiLo a) Gap de baixa (acima de 200 pontos)
b) Mudança de zona do HiLo de vendido para comprado (ou penetração de preço acima da
média móvel das máximas de 10 períodos)
c) Preços andando na máxima do dia

Stop inicial 200 pontos abaixo da mínima do candle que gerou a entrada. Saída quando:

 fechar abaixo do stop inicial


 fechar abaixo da média das mínimas de 10 períodos
 stop gain de 500 pontos
 perda máxima de 300 pontos
 no final do dia

Gap de Alta com Inversão de HiLo para Venda - VENDA:

a) Gap de alta (acima de 200 pontos)


b) Mudança de zona do HiLo de comprado para vendido (ou penetração de preço abaixo da
média móvel das mínimas de 10 períodos)
c) Preços andando na mínima do dia

Stop inicial 200 pontos acima da máxima do candle que gerou a entrada. Saída quando:

 fechar abaixo do stop inicial


 fechar acima da média das mínimas de 10 períodos
 perda máxima de 400 pontos
27
 lucro do trade estiver acima de 300 pontos e máxima do candle menor que máxima anterior
 no final do dia

3.6.1. Considerações gerais sobre os testes

Antes de apresentar os primeiros resultados, vamos entender como foi feito o processo de testes. Através de
indicadores criados no MetaStock, é possível analisar as cotações ao longo do tempo gerar uma série de
dados que contém as seguintes informações:

 Se deu sinal de entrada ou não


 Se gerou stop ou não
 Se deu entrada, qual o preço de compra/venda
 Se gerou stop, qual o preço de compra/venda
 Qual o valor atual do stop
 Qual o “estado” do trade, algo como “0” para fora do mercado e “1” para comprado/vendido

As informações apresentadas anteriormente foram codificadas em diversos indicadores. Na seção “Código


fonte dos indicadores e explorações para MetaStock” é possível encontrar este código e qual a lógica que foi
utilizada para gerar cada informação.

Depois de criados os indicadores, utilizamos o plug-in do TradeSim para o MetaStock, criando uma
exploração que irá navegar por um ou mais ativos especificados e irá criar um arquivo com extensão “.trb” em
uma pasta chamada “C:\TradeSimData”. Neste arquivo ficam registrados todos os trades identificados pela
exploração.

Uma vez criado este arquivo, basta ir ao TradeSim e abri-lo. Estamos interessados no número de pontos que
cada setup é capaz de gerar em um determinado período de tempo. Por esta razão, iremos utilizar sempre
uma posição fixa de 5 mini-contratos. Consideraremos que a margem requerida para cada mini é de R$
2.000,00, de modo que a margem inicial para cada 5 mini-contratos é de R$ 10.000,00. Para 5 minis, cada
ponto equivale a R$ 1,00. Consideramos também uma corretagem igual a R$ 1,00 por mini (preço usual de
corretagem de minis para day trade). Desta forma, os parâmetros a serem utilizados na tela “Trade
Parameters” do TradeSim são:

Trade Parameters
Initial Capital: R$ 50.000,00
Portfolio Limit: 100,00%
Maximum number of open positions: 1
Position Size Model: Equal Dollar Units
Trade Size ($ value): R$ 10.000,00
Pyramid profits: No
Transaction cost per share/contract (Trade Entry): R$ 5,00
Transaction cost per share/contract (Trade Exit): R$ 5,00
Initial Margin: R$ 10.000,00
Point Value: R$ 1,00

Trade Preferences
Trading Instrument: Commodities
Break Even Trades: Process separately
Trade Position Type: Process all trades
Entry Order Type: Default Order
Exit Order Type: Default Order
Minimum Trade Size: R$ 0,00
Accept Partial Trades: No
Volume Filter: Ignore Volume Information
Pyramid Trades: No
Use Level Zero trades only: Yes

Configurados os parâmetros, utilizamos a opção “Backtest” para simular a execução de todos os trades. Esta
opção é a mais adequada para o tipo de teste no qual temos 2 setups, um para a ponta comprada e outro
28
para a ponta vendida, porque temos um único ativo e não há conflitos entre os trades de cada sistema
testado. Caso tivéssemos vários ativos ou setups que gerassem situações nas quais tivéssemos que escolher
entre diferentes entradas possíveis, a melhor opção a ser utilizada é a Simulação de Monte Carlo disponível
na versão Enterprise do TradeSim. Através desta opção, é possível fazer testes exaustivos e gerar diferentes
“trajetórias” de trades, nas quais há um critério aleatório de seleção de entradas quando mais de uma é
possível. Neste caso, os resultados são apresentados como médias das diversas simulações, e também é
fornecido o desvio-padrão de cada parâmetro estimado.

Por fim, vamos recordar alguns dados fornecidos logo no início deste documento:

Entre 3 de Julho de 2006 e 1 de Julho de 2008 (498 dias úteis), o CDI acumulado foi de 25,79%
(http://www.cetip.com.br) e o mini-contrato futuro de Índice Ibovespa variou 20.827 pontos (64.100 – 43.273),
ou 48%. A base de dados do índice futuro utilizada neste estudo foi a série histórica fornecida pela Nelogica
(http://www.nelogica.com.br) em seu software, ProfitChart®. Para o mesmo período a variação do Índice
Bovespa foi de 26.768 pontos (63.396 – 36.628) ou 73%.

Estes serão os benchmarks para comparação do resultado dos setups.

3.6.2. Testes para Gap sem Inversão do HiLo

Este setup foi implementado através dos indicadores “longwave 1” e “longwave 2”, e da exploração “Sim –
longwave 12”, cujo código está disponível na seção “Código fonte dos indicadores e explorações para
MetaStock”.

O conjunto dos setups de compra e venda de gap sem reversão de HiLo apresentou os seguintes resultados
nos testes com o TradeSim (já descontados os custos de corretagem):

Ponta Ponta
Gap sem reversão do HiLo comprada vendida Total
Rentabilidade 10.847 8.706 19.553
Número de trades 57 41 98
% de acertos 64,91% 65,85% 65,31%
Maior ganho 1.674 690 1.674
Maior perda (710) (818) (818)
Máximo drawdown absoluto -1.863
Máximo drawdown relativo -3,65%

Vale lembrar que na ponta vendida definimos stop gain em 700 pontos.

Observamos que, atuando em 98 (19,7%) dos 498 pregões do período, tivemos uma rentabilidade igual a
95,7% (19.928/20.827) da performance de Buy & Hold do ativo que estamos operando. Como consideramos
um capital inicial de R$ 50.000,00, o lucro sobre este capital total foi de 39,86%, ou cerca de 146,2% do CDI -
usamos a fórmula aproximada ((1+39,86%)^(1/498)-1)/((1+25,79%)^(1/498)-1).

Uma consideração importante é que neste teste não foi considerado o efeito de slippage. Na prática, quando
temos um rompimento como o indicado pelo setup, dificilmente iremos conseguir entrar no exato preço da
resistência ou suporte cuja violação aguardamos. Usualmente, no caso do índice, teremos um spread
variando entre 50 e 100 pontos. Para posições maiores, este spread pode representar um problema ainda
maior. Analisaremos o efeito de slippage quando analisarmos o resultado conjunto dos setups de Gap de HiLo
com e sem reversão.

As figuras a seguir mostrar um histograma indicando o número de trades para cada faixa de rentabilidade e a
evolução da curva de capital ao longo do tempo, indicando os períodos de drawdown. Infelizmente, o
TradeSim mostra os resultados apenas de forma percentual, mas podemos verificar que o maior número de
trades na faixa entre 6 e 7% deve-se à lógica de stop gain na ponta vendida.
29
Figura 3.6.2.1. Distribuição de rentabilidade dos trades

Figura 3.6.2.2. Evolução dos resultados ao longo do tempo

30
A título de curiosidade, apresentamos os resultados do setup sem o uso de stop gain na ponta vendida.

Ponta Ponta
Sem stop gain e perda máxima comprada vendida Total
Rentabilidade 11.222 3.728 14.950
Número de trades 57 41 98
% de acertos 64,91% 51,22% 59,18%
Maior ganho 1.674 1.236 1.674
Maior perda (626) (818) (818)
Máximo drawdown absoluto -1.863
Máximo drawdown relativo -3,65%

Após ter realizado esta simulação, verificamos os trades individualmente e observamos que no caso de
operações de venda, o mercado geralmente anda bem rápido quando cai, mas também repica forte após
encontrar um suporte forte ou no final de um dia predominantemente baixista. Aguardar um fechamento acima
da média móvel das máximas (stop móvel que propusemos) é uma estratégia que, por vezes, deixa boa parte
do movimento para o mercado, porque os preços tendem a se afastar bastante destas médias antes de recuar
ou congestionar para que elas se aproximem. Fizemos um estudo de diferentes valores de stop gain e o valor
de 700 pontos foi o que apresentou o melhor resultado.

Nada impede que, na prática, ao invés de a posição ser automaticamente encerrada quando o trade andar
700 pontos, seja colocado neste preço um stop, permitindo que seja possível seguir um pouco mais no
movimento.

Eliminação do stop móvel na média das máximas/mínimas

Tendo em vista a observação acima sobre o uso da média móvel como stop, testamos também uma
estratégia alternativa para saída do trade. Para ambas as pontas, eliminamos este critério de saída. E para a
ponta comprada também eliminamos o critério de fechamento abaixo do stop inicial, deixando apenas um
controle de perda máxima em 800 pontos. Desta forma os critérios de saída são:

 Na ponta comprada, no final do dia ou se o trade andar 800 pontos contra a entrada
 Na ponta vendida, no final do dia ou se fechar acima do stop inicial

Esta variação do setup foi implementada através dos indicadores “longwave 3” e “longwave 4”, e da
exploração “Sim – longwave 34”, cujo código está disponível na seção “Código fonte dos indicadores e
explorações para MetaStock”.

Ponta Ponta
Gap sem reversão do HiLo (2) comprada vendida Total
Rentabilidade 11.889 9.832 21.721
Número de trades 57 41 98
% de acertos 64,91% 68,29% 66,33%
Maior ganho 1.674 690 1.674
Maior perda (810) (818) (818)
Máximo drawdown absoluto -2.391
Máximo drawdown relativo -4,69%

Observamos uma melhora na % de acertos e no resultado total de cada ponta (6% melhor na ponta comprada
e 13% melhor na ponta vendida). Uma maior tolerância a perdas na ponta comprada (sem stop móvel e perda
máxima de 800 pontos) fez com que o máximo drawdown piorasse um pouco, sendo cerca de 500 pontos
maior que o obtido com o uso do stop móvel.

Nas figuras a seguir vemos a nova distribuição de rentabilidade dos trades e a evolução dos lucros ao longo
do tempo.
31
Figura 3.6.2.3. Distribuição de rentabilidade dos trades sem stop móvel

Figura 3.6.2.4. Evolução dos resultados ao longo do tempo, sem stop móvel

32
3.6.3. Testes para Gap com Inversão do HiLo

Este setup foi implementado através dos indicadores “longwave 5” e “longwave 6”, e da exploração “Sim –
longwave 56”, cujo código está disponível na seção “Código fonte dos indicadores e explorações para
MetaStock”.

O conjunto dos setups de compra e venda de gap com reversão de HiLo apresentou os seguintes resultados
nos testes com o TradeSim (já descontados os custos de corretagem):

Ponta Ponta
Gap com reversão do HiLo comprada vendida Total
Rentabilidade 9.213 6.223 15.436
Número de trades 89 93 182
% de acertos 53,93% 48,39% 51,10%
Maior ganho 655 1.374 1.374
Maior perda (330) (410) (410)
Máximo drawdown absoluto -1.771
Máximo drawdown relativo -3,10%

Vale lembrar que na ponta comprada, temos stop gain de 500 pontos e perda máxima de 300 pontos. Na
ponta vendida, temos perda máxima de 400 pontos e saída via stop gain quando o fechamento de um candle
menos o preço de entrada for superior a 300 pontos e a máxima deste candle for menor que a máxima do
candle anterior.

Dos 489 pregões no período, este setup gerou entrada em 182 deles ou 37% dos dias. Sua performance no
período foi de 74% do movimento do próprio índice para uma posição sintética de Buy and Hold na série
histórica e 117% do CDI no período. Consideramos este um setup complementar ao Gap sem Inversão de
HiLo, de modo que podemos criar um trading system combinando os dois setups. Vamos discutir os
resultados combinados na próxima seção.

Figura 3.6.3.1. Distribuição de rentabilidade dos trades

33
Figura 3.6.3.2. Evolução dos resultados ao longo do tempo

3.6.4. Gaps com HiLo

Nesta seção iremos discutir o resultado de um sistema hipotético que utilizasse os dois setups apresentados
anteriormente, o de Gap sem Inversão do HiLo e o de Gap com Inversão do HiLo. Como podem haver
entradas conflitantes, iremos apresentar tanto o resultado de backtests quanto de uma simulação de Monte
Carlo de 2.000 possíveis combinações de entradas.

A combinação dos resultados foi feita através da exploração “Sim – GapHiLo”. O resultado de um backtest
simples de todas as entradas foi o seguinte:

Ponta Ponta
Gap com HiLo comprada vendida Total
Rentabilidade 21.102 16.055 37.157
Número de trades 146 134 280
% de acertos 58,22% 54,48% 56,43%
Maior ganho 1.674 1.374 1.674
Maior perda (810) (818) (818)

Este resultado equivale a 178% da variação de 20.827 pontos do próprio índice e 242% do CDI no período.
Porém, para uma estimativa mais realista e para uma análise de drawdown, devemos analisar o resultado da
simulação de Monte Carlo, e também inserir um modelo de slippage que aproxime os valores de entrada de
pontos mais próximos de desvios devido à atuação humana.

A figura a seguir mostra o número de trades para cada faixa de rentabilidade.

34
Figura 3.6.4.1. Distribuição dos trades por resultado

Sem considerar slippage, o resultado da simulação de Monte Carlo para as duas estratégias combinadas no
período, mantendo-se uma posição constante de 5 mini-contratos e capital inicial de R$ 50.000,00:

Gap Com HiLo Máximo Médio Mínimo


Rentabilidade 46.914 40.877 34.945
Desvio Padrão 2.132
% de acertos 60,85% 58,91% 56,98%
Drawdown absoluto (2.608) (2.401) (1.942)
Drawdown relativo -4,98% -4,31% -3,70%
Número de simulações 2.000
Trades executados por simulação 258

Perceba que em cada simulação foram escolhidos 258 trades do total de 280, pois 22 foram considerados
como entradas conflitantes.

O gráfico a seguir mostra o resultado mês a mês para uma simulação.

35
Figura 3.6.4.2. Resultados mês a mês para uma simulação com as estratégias combinadas

Perceba que houve 4 meses negativos nos 24 considerados no período. O resultado financeiro apresentado
equivale ao número de pontos do setup, pois consideramos uma posição fixa de 5 mini-contratos. A figura a
seguir mostra a evolução dos lucros ao longo do tempo. Note que esta figura é uma combinação das curvas
de evolução apresentadas nas seções anteriores.

Figura 3.6.4.3. Evolução dos resultados ao longo do tempo para uma simulação

36
Podemos melhorar o resultado financeiro se modificarmos a lógica de dimensionamento da posição. Porém,
antes de fazermos isso, vamos considerar um modelo de slippage no qual iremos somar um número entre 0 e
100 a cada entrada, sendo este número escolhido aleatoriamente. Para o preço de saída, colocaremos um
slippage igual à metade do valor utilizado na entrada, pois, devido ao fato de sairmos em fechamento ou via
stop gain, geralmente temos um controle mais preciso sobre a saída. Na prática, em uma operação de compra
estamos entrando até 100 pontos mais caro e saindo até 50 pontos mais barato. O análogo vale para a venda.

Para isto, utilizamos a função Rand disponível no plug-in do TradeSim para o MetaStock e criamos uma
exploração denominada “Sim – GapHiLo(S)”, na qual cada entrada e saída será afetada por este valor.

O resultado dos backtests para este modelo foi:

Ponta Ponta
Gap com HiLo (Slippage) comprada vendida Total
Rentabilidade 11.784 6.328 18.113
Número de trades 146 134 280
% de acertos 57,53% 53,73% 55,71%
Maior ganho 1.538 1.289 1.538
Maior perda (905) (902) (905)

A simulação de Monte Carlo resultou em:

Gap Com HiLo (Slippage) Máximo Médio Mínimo


Rentabilidade 30.737 23.168 16.582
Desvio Padrão 2.100
% de acertos 60,47% 58,14% 55,81%
Drawdown absoluto (4.150) (3.368) (2.463)
Drawdown relativo -8,08% -5,82% -4,80%
Número de simulações 2.000
Trades executados por simulação 258

Perceba que, se utilizarmos como referência o valor médio de lucro obtido na simulação de Monte Carlo,
teremos feito 111,2% do movimento do índice no período e 46% sobre o capital, ou 165% do CDI. Com a
inserção do slippage, já era de se esperar um drawdown maior que o observado nas simulações anteriores.

3.6.5. Estratégia combinada com Slippage e Manejo de Risco

Para finalizar, vamos observar uma situação mais realista ainda para o uso do modelo descrito na seção
anterior. Ao abrir cada posição, iremos analisar a distância entre o preço de entrada e o stop inicial, e com
base nesta perda esperada, iremos dimensionar nossa posição de modo a nunca arriscar mais que 2% do
capital total em um trade. Por exemplo, se a entrada se o stop loss é de 300 pontos, isto significa que a cada
5 minis poderemos perder R$ 300,00. Para um capital inicial de R$ 50.000,00, temos que 2% = R$ 1.000,00.
Dessa forma, como estamos operando de 5 em 5 minis, a máxima posição que podemos montar é de 15
minis, para a qual, caso fôssemos estopados, perderíamos R$ 900,00.

Observe que, apesar de estarmos alavancando um pouco mais, estamos limitando a nossa perda pela
presença de um stop claro.

No TradeSim, limitamos o máximo capital arriscado em um trade em 2%, no máximo 1 posição em aberto e
20% de Portfolio Heat. Os parâmetros para a simulação no TradeSim são mostrados a seguir.

37
Trade Parameters
Initial Capital: R$ 50.000,00
Portfolio Limit: 100,00%
Maximum number of open positions: 1
Position Size Model: Fixed Percent Risk
Percentage of capital risked per trade: 2,00%
Position size limit: 100,00%
Portfolio Heat: 20,00%
Pyramid profits: No
Transaction cost per share/contract (Trade Entry): R$ 5,00
Transaction cost per share/contract (Trade Exit): R$ 5,00
Initial Margin: R$ 10.000,00
Point Value: R$ 1,00

Trade Preferences
Trading Instrument: Commodities
Break Even Trades: Process separately
Trade Position Type: Process all trades
Entry Order Type: Default Order
Exit Order Type: Default Order
Minimum Trade Size: R$ 0,00
Accept Partial Trades: No
Volume Filter: Ignore Volume Information
Pyramid Trades: No
Use Level Zero trades only: Yes

O resultado foi o seguinte:

Gap Com HiLo (Slippage e Manejo) Máximo Médio Mínimo


Rentabilidade 60.730 47.950 32.424
Desvio Padrão 4.580
% de acertos 60,00% 58,27% 56,08%
Drawdown absoluto (9.518) (7.410) (6.546)
Drawdown relativo -18,41% -14,34% -12,67%
Número de simulações 2.000
Trades executados por simulação 255

Perceba que o drawdown agora não é mais interpretado em pontos, mas sim financeiramente. O máximo
drawdown relativo foi uma perda de 18%. A rentabilidade média sobre o valor inicial de R$ 50.000,00 foi de
47.950, ou seja 95%, contra 48% da variação do contrato futuro de mini-índice e 73% da variação do índice à
vista. A estratégia rendeu 293% do CDI no período.

Nosso objetivo aqui, ao apresentar estes dados, é de que os critérios de saída e a regra para
dimensionamento da posição são tão importantes quando o critério de entrada. E geralmente quando
procuramos um setup, focamos apenas na regra de entrada. Sem os critérios de stop gain, perda máxima e
sem a lógica de money management indicada, seria praticamente inviável que os métodos apresentados
gerassem algum lucro.

Apresentamos a seguir alguns gráficos que mostram os resultados para uma das simulações.

38
Figura 3.6.5.1. Evolução dos resultados ao longo do tempo para uma simulação

Figura 3.6.5.2. Resultados mês a mês para uma simulação

39
Figura 3.6.5.3. Distribuição de simulações de acordo com o lucro obtido

Figura 3.6.5.4. Distribuição de simulações de acordo com o máximo drawdown percentual

40
4. Considerações finais
Recordamos que este estudo analisou as técnicas propostas por um período de tempo que pode ser
considerado estatisticamente insuficiente (apenas 2 anos), mas o mais importante aqui é apresentar um
modelo de como descrever setups e de como testá-los contra dados históricos. Para que cada técnica seja
utilizada manualmente, o trader deve fazer os seus próprios testes, verificar os piores trades possíveis (vide a
lista de trades no final deste texto) e como ele se comportaria em cada situação. Além disso, é importante
testar cada setup como o mercado em movimento por um período de tempo, seja com posições pequenas ou
via “paper trading”.

Encorajamos o leitor a navegar pelos trades realizados e interpretar possíveis diferenças entre os valores
registrados pelo simulador e os valores que seriam resultantes da atuação de um trader humano. Caso o leitor
encontre alguma inconsistência, por favor entre em contato com os autores, que verificaremos na medida do
possível.

Observe que boa parte dos bons resultados foi obtida graças a estratégias alternativas de saída,
especialmente critérios de stop gain e perda máxima. Por vezes, somos tentados pela ganância a não seguir
este tipo de regra. Achamos que o mercado vai voltar aos preços iniciais ou que vai andar um pouco mais a
favor do trade. O uso de setups com pouca ou nenhuma margem de subjetividade e sua validação contra
dados históricos nos ajuda a ter uma confiança adicional. Porém, no final, o verdadeiro lucro irá depender do
nosso nível de disciplina.

Verificamos, ainda, que o uso de uma regra de dimensionamento de posição adequada (manejo de risco,
money management) pode nos ajudar a obter uma rentabilidade financeira interessante, superior à
rentabilidade em pontos esperada pelo setup. Estressamos o ponto de que um setup não é simplesmente
uma regra de entrada, mas também um conjunto de critérios de saída e de regras de manejo de risco.
Simulações sobre dados históricos podem nos ajudar a identificar quais os melhores parâmetros a serem
utilizados.

41
5. Referências
Bernstein, Jake. The Compleat Day Trader: Volume II. McGraw-Hill, 1998.

Bollinger, John. Bollinger on Bollinger Bands. McGraw-Hill, 2002.

Compuvision Australia. AN-2 Implementing Volatility Trailing Stops the Simple Way. TradeSim® Manuals,
2005. http://www.forexfactory.com/attachment.php?attachmentid=6419&d=1150337272

Krausz, Robert. New Swing Chartist, Dynamic Fibonacci Channels. Fibonacci Trader Journal, Volume 1, Issue
2. http://www.fibonaccitrader.com/journals/freejournal.htm

Velez, Oliver & Capra, Greg. Tools and Tactics for the Master Day Trader: Battle-Tested Techniques for Day,
Swing, and Position Traders. McGraw-Hill, 2000.

Vilares, Lauro. Como Operar Gaps. Palestra Virtual, Leandro & Stormer Trading.
http://www.leandrostormer.com.br/View/Publico/palestras.aspx

Tharp, V. K. Trade Your Way To Financial Freedom. McGraw-Hill, 2nd. ed. 2006.

42
6. Código fonte dos indicadores e explorações para MetaStock

6.1. HiLoZone

Identifica as zonas compradas e vendidas do HiLo Activator.

period:=Input("Period",1,100,10);

MovH:=Ref(Mov(H,period,S),-1);
MovL:=Ref(Mov(L,period,S),-1);

HLd:=If(C>MovH,1,If(C<MovL,-1,0));
HLv:=ValueWhen(1,HLd<>0,HLd);

HiLoZone:=If(HLv=-1,-1,1);

Change:=If(HiLoZone<>Ref(HiLoZone,-1),1,0);
BullishChange:=Change AND HiLoZone=1;
BearishChange:=Change AND HiLoZone=-1;

HiLoZone;

6.2. Longwave 1

Gap de Alta com HiLo Comprado.

StopGain:=0;
MaxLoss:=0;

DayBegins:=DayOfMonth()<>Ref(DayOfMonth(),-1);
DayEnds:=DayOfMonth()<>Ref(DayOfMonth(),1);
YesterdayClose:=ValueWhen(1,DayEnds,C);
TodaysOpening:=ValueWhen(1,DayBegins,O);
TodayMin:=LowestSince(1,DayBegins,L);

NoChangeInHiLoZone:=DayOfMonth()<>ValueWhen(1,Fml("HiLoZone")=-1,DayOfMonth());
Gap:=If(DayEnds,TodaysOpening-Ref(YesterdayClose,-1),TodaysOpening-YesterdayClose);
NthBar:=BarsSince(DayBegins);
InitialRangeHigh:=If(NthBar<4,HighestSince(1,DayBegins,H),ValueWhen(1,NthBar=3,HHV(H,4)));

Signal:=BarsSince(DayBegins)>3 AND Gap>0 AND Abs(Gap)>200 AND NoChangeInHiLoZone AND C>Mov(C,10,S) AND
TodayMin>(YesterdayClose+100) AND H>InitialRangeHigh;
NoSignalToday:=DayOfMonth()<>If(Signal,ValueWhen(2,Signal,DayOfMonth()),ValueWhen(1,Signal,DayOfMonth()));
Signal:=Signal AND NoSignalToday;

InitialStop:=ValueWhen(1,Signal,L-200);
Stop:=DayOfMonth()<>Ref(DayOfMonth(),+1) OR C<Ref(Mov(L,10,S),-1) OR C<InitialStop;

EntryPrice:=Max(InitialRangeHigh,O);
Trigger:=ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,LONG,TRIGGER);
ExitPrice:=If(Trigger<-1,ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,LONG,EXITPRICE),C);

Entry:=Trigger>0;
Exit:=Trigger<0;

ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,LONG,STATE);

6.3. Longwave 2

Gap de Baixa com HiLo Vendido.

StopGain:=700;
MaxLoss:=0;

43
DayBegins:=DayOfMonth()<>Ref(DayOfMonth(),-1);
DayEnds:=DayOfMonth()<>Ref(DayOfMonth(),1);
YesterdayClose:=ValueWhen(1,DayEnds,C);
TodaysOpening:=ValueWhen(1,DayBegins,O);
TodayMax:=HighestSince(1,DayBegins,H);
NoChangeInHiLoZone:=DayOfMonth()<>ValueWhen(1,Fml("HiLoZone")=1,DayOfMonth());
Gap:=If(DayEnds,TodaysOpening-Ref(YesterdayClose,-1),TodaysOpening-YesterdayClose);
NthBar:=BarsSince(DayBegins);
InitialRangeLow:=If(NthBar<4,LowestSince(1,DayBegins,L),ValueWhen(1,NthBar=3,LLV(L,4)));

Signal:=BarsSince(DayBegins)>3 AND Gap<0 AND Abs(Gap)>200 AND NoChangeInHiLoZone AND C<Mov(C,10,S) AND
TodayMax<YesterdayClose-100 AND L<InitialRangeLow;
NoSignalToday:=DayOfMonth()<>If(Signal,ValueWhen(2,Signal,DayOfMonth()),ValueWhen(1,Signal,DayOfMonth()));
Signal:=Signal AND NoSignalToday;

InitialStop:=ValueWhen(1,Signal,H+200);
Stop:=DayOfMonth()<>Ref(DayOfMonth(),+1) OR C>Ref(Mov(H,10,S),-1) OR C>InitialStop;

EntryPrice:=Min(InitialRangeLow,O);

Trigger:=ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,SHORT,TRIGGER);
ExitPrice:=If(Trigger<-
1,ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,SHORT,EXITPRICE),C);

Entry:=Trigger>0;
Exit:=Trigger<0;

ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,SHORT,STATE);

6.4. Exploração “Sim – longwave 12”

{ Sim - longwave 1/2}

EntryTrigger1:= FmlVar("longwave 1","ENTRY");


EntryPrice1:= FmlVar("longwave 1","ENTRYPRICE");
ExitTrigger1:= FmlVar("longwave 1","EXIT");
ExitPrice1:= FmlVar("longwave 1","EXITPRICE");

InitialStop1:=FmlVar("longwave 1","INITIALSTOP");

ExtFml("TradeSim.Initialize");
ExtFml("TradeSim.DisableProtectiveStop");
ExtFml("TradeSim.EnablePriceFilter");

ExtFml("TradeSim.SetValue",SystemID,1);
ExtFml( "TradeSim.RecordTrades",

"Sim - longwave 12", { filename }

LONG, { long positions }


EntryTrigger1, { entry criteria }
EntryPrice1, { entry price }
InitialStop1, { initial stop loss }
ExitTrigger1, { exit criteria }
ExitPrice1, { exit price }
START);

EntryTrigger2:= FmlVar("longwave 2","ENTRY");


EntryPrice2:= FmlVar("longwave 2","ENTRYPRICE");
ExitTrigger2:= FmlVar("longwave 2","EXIT");
ExitPrice2:= FmlVar("longwave 2","EXITPRICE");

InitialStop2:=FmlVar("longwave 2","INITIALSTOP");

ExtFml("TradeSim.SetValue",SystemID,2);
ExtFml( "TradeSim.RecordTrades",

"Sim - longwave 12", { filename }

SHORT, { short positions }


EntryTrigger2, { entry criteria }
EntryPrice2, { entry price }
InitialStop2, { initial stop loss }
ExitTrigger2, { exit criteria }

44
ExitPrice2, { exit price }
CONTINUE);

6.5. Longwave 3

Gap de Alta com HiLo Comprado, com saída via perda máxima ou no final do dia apenas. O stop inicial e o
stop móvel do HiLo foram removidos.

StopGain:=0;
MaxLoss:=800;

DayBegins:=DayOfMonth()<>Ref(DayOfMonth(),-1);
DayEnds:=DayOfMonth()<>Ref(DayOfMonth(),1);
YesterdayClose:=ValueWhen(1,DayEnds,C);
TodaysOpening:=ValueWhen(1,DayBegins,O);
TodayMin:=LowestSince(1,DayBegins,L);

NoChangeInHiLoZone:=DayOfMonth()<>ValueWhen(1,Fml("HiLoZone")=-1,DayOfMonth());
Gap:=If(DayEnds,TodaysOpening-Ref(YesterdayClose,-1),TodaysOpening-YesterdayClose);
NthBar:=BarsSince(DayBegins);
InitialRangeHigh:=If(NthBar<4,HighestSince(1,DayBegins,H),ValueWhen(1,NthBar=3,HHV(H,4)));

Signal:=BarsSince(DayBegins)>3 AND Gap>0 AND Abs(Gap)>200 AND NoChangeInHiLoZone AND C>Mov(C,10,S) AND
TodayMin>(YesterdayClose+100) AND H>InitialRangeHigh;
NoSignalToday:=DayOfMonth()<>If(Signal,ValueWhen(2,Signal,DayOfMonth()),ValueWhen(1,Signal,DayOfMonth()));
Signal:=Signal AND NoSignalToday;

InitialStop:=ValueWhen(1,Signal,L-200);
Stop:=DayOfMonth()<>Ref(DayOfMonth(),+1);

EntryPrice:=Max(InitialRangeHigh,O);
Trigger:=ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,LONG,TRIGGER);
ExitPrice:=If(Trigger<-1,ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,LONG,EXITPRICE),C);

Entry:=Trigger>0;
Exit:=Trigger<0;

6.6. Longwave 4

Gap de Baixa com HiLo Vendido, com saída via stop gain, stop inicial ou stop no final do dia. O stop móvel via
HiLo foi removido.

StopGain:=700;
MaxLoss:=0;

DayBegins:=DayOfMonth()<>Ref(DayOfMonth(),-1);
DayEnds:=DayOfMonth()<>Ref(DayOfMonth(),1);
YesterdayClose:=ValueWhen(1,DayEnds,C);
TodaysOpening:=ValueWhen(1,DayBegins,O);
TodayMax:=HighestSince(1,DayBegins,H);
NoChangeInHiLoZone:=DayOfMonth()<>ValueWhen(1,Fml("HiLoZone")=1,DayOfMonth());
Gap:=If(DayEnds,TodaysOpening-Ref(YesterdayClose,-1),TodaysOpening-YesterdayClose);
NthBar:=BarsSince(DayBegins);
InitialRangeLow:=If(NthBar<4,LowestSince(1,DayBegins,L),ValueWhen(1,NthBar=3,LLV(L,4)));

Signal:=BarsSince(DayBegins)>3 AND Gap<0 AND Abs(Gap)>200 AND NoChangeInHiLoZone AND C<Mov(C,10,S) AND
TodayMax<YesterdayClose-100 AND L<InitialRangeLow;
NoSignalToday:=DayOfMonth()<>If(Signal,ValueWhen(2,Signal,DayOfMonth()),ValueWhen(1,Signal,DayOfMonth()));
Signal:=Signal AND NoSignalToday;

InitialStop:=ValueWhen(1,Signal,H+200);
Stop:=DayOfMonth()<>Ref(DayOfMonth(),+1) OR C>InitialStop;

EntryPrice:=Min(InitialRangeLow,O);

Trigger:=ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,SHORT,TRIGGER);
ExitPrice:=If(Trigger<-
1,ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,SHORT,EXITPRICE),C);

45
Entry:=Trigger>0;
Exit:=Trigger<0;

6.7. Exploração “Sim – longwave 34”

O código é idêntico ao da exploração “Sim – longwave 12”, exceto pela troca dos índices 1 e 2. Obtenha o
arquivo ZIP com a instalação dos indicadores e explorações para o MetaStock a fim de ver qualquer código
não listado aqui. Veja mais detalhes na seção “Ferramentas e dados utilizados nos testes”.

6.8. Longwave 5

Gap de Baixa com Inversão do HiLo de Vendido para Comprado.

StopGain:=500;
MaxLoss:=300;

DayBegins:=DayOfMonth()<>Ref(DayOfMonth(),-1);
DayEnds:=DayOfMonth()<>Ref(DayOfMonth(),1);
YesterdayClose:=ValueWhen(1,DayEnds,C);
TodaysOpening:=ValueWhen(1,DayBegins,O);
HighestToday:=HighestSince(1,DayBegins,H);
HighestToday:=If(H=HighestToday,Ref(HighestSince(1,DayBegins,H),-1),HighestToday);

Gap:=If(DayEnds,TodaysOpening-Ref(YesterdayClose,-1),TodaysOpening-YesterdayClose);
NthBar:=BarsSince(DayBegins);

BullishChangeInHiLo:=DayOfMonth()=ValueWhen(1,H>Ref(Mov(H,10,S),-1),DayOfMonth());

Signal:=NthBar<>0 AND Gap<0 AND Abs(Gap)>200 AND BullishChangeInHiLo AND H>HighestToday;


NoSignalToday:=DayOfMonth()<>If(Signal,ValueWhen(2,Signal,DayOfMonth()),ValueWhen(1,Signal,DayOfMonth()));

Signal:=Signal AND NoSignalToday;


InitialStop:=ValueWhen(1,Signal,L-200);

Stop:=DayOfMonth()<>Ref(DayOfMonth(),+1) OR C<InitialStop OR C<Ref(Mov(L,10,S),-1);

EntryPrice:=Max(Max(O,HighestToday),Ref(Mov(H,10,S),-1));

Trigger:=ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,LONG,TRIGGER);
ExitPrice:=If(Trigger<-1,ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,LONG,EXITPRICE),C);

Entry:=Trigger>0;
Exit:=Trigger<0;

ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,LONG,STATE);

6.9. Longwave 6

Gap de Alta com Inversão do HiLo de Comprado para Vendido.

StopGain:=0;
MaxLoss:=400;

DayBegins:=DayOfMonth()<>Ref(DayOfMonth(),-1);
DayEnds:=DayOfMonth()<>Ref(DayOfMonth(),1);

YesterdayClose:=ValueWhen(1,DayEnds,C);
TodaysOpening:=ValueWhen(1,DayBegins,O);
LowestToday:=LowestSince(1,DayBegins,L);
LowestToday:=If(L=LowestToday,Ref(LowestSince(1,DayBegins,L),-1),LowestToday);
Gap:=If(DayEnds,TodaysOpening-Ref(YesterdayClose,-1),TodaysOpening-YesterdayClose);
NthBar:=BarsSince(DayBegins);
BearishChangeInHiLo:=DayOfMonth()=ValueWhen(1,L<Ref(Mov(L,10,S),-1),DayOfMonth());

Signal:=NthBar<>0 AND Gap>0 AND Abs(Gap)>200 AND BearishChangeInHiLo AND L<LowestToday;


NoSignalToday:=DayOfMonth()<>If(Signal,ValueWhen(2,Signal,DayOfMonth()),ValueWhen(1,Signal,DayOfMonth()));

46
Signal:=Signal AND NoSignalToday;

InitialStop:=ValueWhen(1,Signal,H+200);

Stop:=DayOfMonth()<>Ref(DayOfMonth(),+1) OR C>InitialStop OR C>Ref(Mov(H,10,S),-1);

EntryPrice:=Min(Min(O,LowestToday),Ref(Mov(L,10,S),-1));

Profit:=ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,SHORT,PROFIT);

Stop:=Stop OR (Profit>300 AND H<Ref(H,-1));

Trigger:=ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,SHORT,TRIGGER);
ExitPrice:=If(Trigger<-
1,ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,SHORT,EXITPRICE),C);

Entry:=Trigger>0;
Exit:=Trigger<0;

ExtFml("TestHelper.Trigger",EntryPrice,Signal,Stop,StopGain,MaxLoss,SHORT,STATE);

6.10. Exploração “Sim – longwave 56”

O código é idêntico ao da exploração “Sim – longwave 12”, exceto pela troca dos índices 1 e 2. Obtenha o
arquivo ZIP com a instalação dos indicadores e explorações para o MetaStock a fim de ver qualquer código
não listado aqui. Veja mais detalhes na seção “Ferramentas e dados utilizados nos testes”.

6.11. Exploração “Sim – GapHiLo”

Combinação das estratégias de gap com e sem inversão do HiLo.

SlippageLong:=0;
SlippageShort:=0;

ExtFml("TradeSim.Initialize");
ExtFml("TradeSim.DisableProtectiveStop");
ExtFml("TradeSim.EnablePriceFilter");
ExtFml("TradeSim.SetValue",SystemID,3);
ExtFml("TradeSim.RecordTrades",
"Sim - GapHiLo",
LONG,
FmlVar("longwave 3","ENTRY"),
FmlVar("longwave 3","ENTRYPRICE")+SlippageLong,
FmlVar("longwave 3","INITIALSTOP")+SlippageLong,
FmlVar("longwave 3","EXIT"),
FmlVar("longwave 3","EXITPRICE")-SlippageLong,
START);
ExtFml("TradeSim.SetValue",SystemID,4);
ExtFml( "TradeSim.RecordTrades",
"Sim - GapHiLo",
SHORT,
FmlVar("longwave 4","ENTRY"),
FmlVar("longwave 4","ENTRYPRICE")+SlippageShort,
FmlVar("longwave 4","INITIALSTOP")+SlippageShort,
FmlVar("longwave 4","EXIT"),
FmlVar("longwave 4","EXITPRICE")-SlippageShort,
CONTINUE);
ExtFml("TradeSim.SetValue",SystemID,5);
ExtFml( "TradeSim.RecordTrades",
"Sim - GapHiLo",
LONG,
FmlVar("longwave 5","ENTRY"),
FmlVar("longwave 5","ENTRYPRICE")+SlippageLong,
FmlVar("longwave 5","INITIALSTOP"),
FmlVar("longwave 5","EXIT"),
FmlVar("longwave 5","EXITPRICE")-SlippageLong,
CONTINUE);
ExtFml("TradeSim.SetValue",SystemID,6);
ExtFml( "TradeSim.RecordTrades",
47
"Sim - GapHiLo",
SHORT,
FmlVar("longwave 6","ENTRY"),
FmlVar("longwave 6","ENTRYPRICE")+SlippageShort,
FmlVar("longwave 6","INITIALSTOP"),
FmlVar("longwave 6","EXIT"),
FmlVar("longwave 6","EXITPRICE")-SlippageShort,
CONTINUE);

6.12. Exploração “Sim – Gap HiLo(S)”

Esta exploração introduz um modelo de slippage para entrada e saída do trade.

SlippageLong:=ExtFml("TradeSim.Rand")*100;
SlippageShort:=-ExtFml("TradeSim.Rand")*100;

ExtFml("TradeSim.Initialize");
ExtFml("TradeSim.DisableProtectiveStop");
ExtFml("TradeSim.EnablePriceFilter");
ExtFml("TradeSim.SetValue",SystemID,3);
ExtFml("TradeSim.RecordTrades",
"Sim - GapHiLo(S)",
LONG,
FmlVar("longwave 3","ENTRY"),
FmlVar("longwave 3","ENTRYPRICE")+SlippageLong,
FmlVar("longwave 3","INITIALSTOP")+SlippageLong,
FmlVar("longwave 3","EXIT"),
FmlVar("longwave 3","EXITPRICE")-SlippageLong/2,
START);
ExtFml("TradeSim.SetValue",SystemID,4);
ExtFml( "TradeSim.RecordTrades",
"Sim - GapHiLo(S)",
SHORT,
FmlVar("longwave 4","ENTRY"),
FmlVar("longwave 4","ENTRYPRICE")+SlippageShort,
FmlVar("longwave 4","INITIALSTOP")+SlippageShort,
FmlVar("longwave 4","EXIT"),
FmlVar("longwave 4","EXITPRICE")-SlippageShort,
CONTINUE);
ExtFml("TradeSim.SetValue",SystemID,5);
ExtFml( "TradeSim.RecordTrades",
"Sim - GapHiLo(S)",
LONG,
FmlVar("longwave 5","ENTRY"),
FmlVar("longwave 5","ENTRYPRICE")+SlippageLong,
FmlVar("longwave 5","INITIALSTOP"),
FmlVar("longwave 5","EXIT"),
FmlVar("longwave 5","EXITPRICE")-SlippageLong/2,
CONTINUE);
ExtFml("TradeSim.SetValue",SystemID,6);
ExtFml( "TradeSim.RecordTrades",
"Sim - GapHiLo(S)",
SHORT,
FmlVar("longwave 6","ENTRY"),
FmlVar("longwave 6","ENTRYPRICE")+SlippageShort,
FmlVar("longwave 6","INITIALSTOP"),
FmlVar("longwave 6","EXIT"),
FmlVar("longwave 6","EXITPRICE")-SlippageShort/2,
CONTINUE);

48
7. Ferramentas e dados utilizados nos testes
A base de dados do mini-contrato futuro de Índice Ibovespa contém candles do gráfico de 30’ da série
histórica do índice futuro – que consolida todos os vencimentos, exportados a partir do ProfitChart®, da
Nelogica – http://www.nelogica.com.br. O período correspondente aos dados é de a 1/7/2006 a 1/7/2008.

Esta base está disponível em formato ASCII compatível para importação com o Metastock no arquivo
WINFUT30.txt.

Para a programação dos setups estudados, utilizamos a versão 9.0 do MetaStock. Com a versão 4.2.2 do
TradeSim, foi possível analisar os trades gerados e realizar as simulações.

Fornecemos, a fim de possibilitar a repetição dos testes realizados, os seguintes arquivos:

Arquivo Descrição
WINFUT30.txt Série histórica utilizada em formato ASCII compatível para importação via The
Downloader no MetaStock
Sim - longwave 12.trb Base de dados para o TradeSim com os trades registrados para o setup de Gap
sem Inversão do HiLo. O arquivo .ses com o mesmo nome contém as
configurações da simulação
Sim – longwave 34.trb Base de dados para o TradeSim com os trades do setup Gap sem inversão do
HiLo, sem stop móvel. O arquivo .ses com o mesmo nome contém as
configurações da simulação
Sim – longwave 56.trb Base de dados para o TradeSim com os trades do setup Gap de Alta/Baixa com
Inversão do HiLo. O arquivo .ses com o mesmo nome contém as configurações
da simulação.
Sim – GapHiLo.trb Base de dados para o TradeSim com os trades da estratégia combinada dos
setups de Gap com e sem inversão do HiLo. O arquivo .ses com o mesmo nome
contém as configurações da simulação.
Sim – GapHiLo(S).trb Base de dados para o TradeSim com os trades da estratégia combinada dos
setups de Gap com e sem inversão do HiLo, adicionando-se slippage às entradas
e saídas. O arquivo .ses com o mesmo nome contém as configurações da
simulação.
FOSetup.exe Instalador (self-extractor) dos indicadores, explorações e da DLL TestHelper para
o Metastock 9
MS90EXPL.DTA e Contém os indicadores, explorações e a DLL TestHelper para importação via
MS90FORM.DTA Organizer do Metastock 9, caso o instalador não funcione.

49
8. Registro dos trades simulados para cada setup
Todos os trades simulados estão disponíveis na planilha Trades.xls, junto com os demais arquivos. Cada aba
corresponde a um setup combinando operações de compra e venda. Temos as seguintes abas:

Aba Setup
longwave12 Gap sem inversão de HiLo
longwave34 Gap sem inversão de HiLo e sem stop móvel
longwave56 Gap com inversão de HiLo
GapHiLo(S) Combinação dos setups com slippage

9. Código Fonte da DLL TestHelper


Em anexo o código fonte da DLL TestHelper, para a visualização das lógicas de stop gain e perda máxima, e
exemplos de uso das funções.

#include <windows.h>
#include <string.h>
#include <float.h>
#include <math.h>
#include <stdlib.h>

#include "MSXStruc.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
TestHelper v1.0
by Isac Costa, July 2008

-------------------------------------------------------------------------------------

[f0] VolatilityStop(ThresholdPrice,Volatility,Position)

A volatility-based trailing stop. If the Threshold Price closes below the volatility, then
a long position is stopped. While it is not stopped, the stop level moves upward as the max
value between the previous stop level and the volatility data.

Sample Usage:
ExtFml("TestHelper.VolatilityStop",C,C-2*ATR(10),LONG) or
ExtFml("TestHelper.VolatilityStop",C,C+2*ATR(10),SHORT)

[a0] ThresholdPrice (DataArray): is the price to compare with the previous stop value
to see if a stop has been generated. This is usually the close price.
[a1] Volatility (DataArray): is the expression containing the reference price minus/plus
a volatility factor, such as C-2*ATR(10).
[a2] Position (CustomString): can be "LONG", "L", "SHORT" or "S".

Returns: the value of the trailing stop

-------------------------------------------------------------------------------------

[f1] ConditionalVolatilityStop(ThresholdPrice,Volatility,Condition,NewStopLevel,Position)

Until Condition is valid, if ThresholdPrice closes below Volatility, a long position will be
stopped. After Condition is valid, stop moves upward according to NewStopLevel.

Sample Usage:

ExtFml("TestHelper.ConditionalVolatilityStop",C,C-2*ATR(10),H>(Mov(C,10,S)+2*ATR(10)),L,LONG)
ExtFml("TestHelper.ConditionalVolatilityStop",C,C-2*ATR(10),H>(Mov(C,10,S)+2*ATR(10)),H,SHORT)

-------------------------------------------------------------------------------------

50
[f2] Trigger(EntryPrice,Signal,Stop,StopGain,MaxLoss,Position,Export)

[a0] EntryPrice(DataArray): the entry price to be used for every entry signal.
[a1] Signal(DataArray): 1 for entry, 0 for no entry.
[a2] Stop(DataArray): 1 for stop, 0 for no stop.
[a3] StopGain(DataArray): value to be used for stop gain, use 0 to disable.
[a4] MaxLoss(DataArray): maximum loss accepted, use <=0 to disable.
[a5] Position (CustomString): can be "LONG", "L", "SHORT" or "S".
[a6] Export (CustomString): can be "TRIGGER", "T", "STATE", "S",
"PROFIT", "P", "ENTRYPRICE", "E" or "EXITPRICE", "X".

Returns: 0 to no trigger, 1 to entry trigger, -1 to exit trigger with stop loss, -2 to exit trigger with stop
gain

Sample Usage:

Trigger:=ExtFml("TestHelper.Trigger",C,Cross(Mov(C,5,S),Mov(C,21,S)),Cross(Mov(C,21,S),Mov(C,5,S)),ATR(10),LONG,
TRIGGER)
Trigger:=ExtFml("TestHelper.Trigger",C,Cross(Mov(C,21,S),Mov(C,5,S)),Cross(Mov(C,5,S),Mov(C,21,S)),0,SHORT,TRIGG
ER)

*/

#define MSXMax(a,b) (((a) > (b)) ? (a) : (b))


#define MSXMin(a,b) (((a) < (b)) ? (a) : (b))

// -----------------------------------------------------------------------------------------

BOOL __stdcall MSXInfo (MSXDLLDef *def) {


strncpy_s (def->szCopyright, "Test Helper MSX DLL, Copyright (c) Isac Costa, 2008",
sizeof(def->szCopyright)-1);
def->iNFuncs = 3; // number of functions being exported
def->iVersion = MSX_VERSION;
return MSX_SUCCESS;
}

// -----------------------------------------------------------------------------------------

BOOL __stdcall MSXNthFunction (int function, MSXFuncDef *def)


{
int res = MSX_SUCCESS; // no error

switch (function) {
case 0:
strcpy_s (def->szFunctionName, "VolatilityStop");
strcpy_s (def->szFunctionDescription, "A volatility-based trailing stop");
def->iNArguments = 3;
break;
case 1:
strcpy_s (def->szFunctionName, "ConditionalVolatilityStop");
strcpy_s (def->szFunctionDescription, "A volatility-based trailing stop that tightens stop at a
given condition");
def->iNArguments = 5;
break;
case 2:
strcpy_s (def->szFunctionName, "Trigger");
strcpy_s (def->szFunctionDescription, "Entry and exit triggers for a trading system");
def->iNArguments = 7;
break;
default:
res = MSX_ERROR; // This will help MSXTest find errors in your code
break;
}
return res;
}

// -----------------------------------------------------------------------------------------

BOOL __stdcall MSXNthArg (int function, int argument,


MSXFuncArgDef *def)
{
BOOL res = MSX_SUCCESS;

def->iNCustomStrings = 0;

switch (function) {
case 0:

51
switch (argument) {
case 0:
def->iArgType = MSXDataArray;
strcpy_s (def->szArgName, "ThresholdPrice");
break;
case 1:
def->iArgType = MSXDataArray;
strcpy_s (def->szArgName, "Volatility");
break;
case 2:
def->iArgType = MSXCustom;
def->iNCustomStrings = 4;
strcpy_s (def->szArgName, "Position");
break;
default:
res = MSX_ERROR;
break;
}
break;
case 1:
switch (argument) {
case 0:
def->iArgType = MSXDataArray;
strcpy_s (def->szArgName, "ThresholdPrice");
break;
case 1:
def->iArgType = MSXDataArray;
strcpy_s (def->szArgName, "Volatility");
break;
case 2:
def->iArgType = MSXDataArray;
strcpy_s (def->szArgName, "Condition");
break;
case 3:
def->iArgType = MSXDataArray;
strcpy_s (def->szArgName, "NewStopLevel");
break;
case 4:
def->iArgType = MSXCustom;
def->iNCustomStrings = 4;
strcpy_s (def->szArgName, "Position");
break;
default:
res = MSX_ERROR;
break;
}
break;
case 2:
switch (argument) {
case 0:
def->iArgType = MSXDataArray;
strcpy_s (def->szArgName, "EntryPrice");
break;
case 1:
def->iArgType = MSXDataArray;
strcpy_s (def->szArgName, "Signal");
break;
case 2:
def->iArgType = MSXDataArray;
strcpy_s (def->szArgName, "Stop");
break;
case 3:
def->iArgType = MSXDataArray;
strcpy_s (def->szArgName, "StopGain");
break;
case 4:
def->iArgType = MSXDataArray;
strcpy_s (def->szArgName, "MaxDataLoss");
break;
case 5:
def->iArgType = MSXCustom;
def->iNCustomStrings = 4;
strcpy_s (def->szArgName, "Position");
break;
case 6:
def->iArgType = MSXCustom;
def->iNCustomStrings = 10;

52
strcpy_s (def->szArgName, "Export");
break;
default:
res = MSX_ERROR;
break;
}
break;
default:
res = MSX_ERROR; // This will help MSXTest find errors in your code
break;
}

return res;
}

// -----------------------------------------------------------------------------------------

BOOL __stdcall MSXNthCustomString (int function, int argument, int str,


MSXFuncCustomString *customStr)
{

BOOL res = MSX_SUCCESS;

customStr->szString[0] = '\0';
customStr->iID = -1;

typedef struct {
char *szString;
int iID;
} LocalStringElement;

LocalStringElement position_values[] = {
{"LONG",0}, {"L", 0},
{"SHORT",1}, {"S", 1},
};

LocalStringElement export_values[] = {
{"TRIGGER",0}, {"T", 0},
{"STATE",1}, {"S", 1},
{"PROFIT",2}, {"P", 2},
{"ENTRYPRICE",3}, {"E", 3},
{"EXITPRICE",4}, {"X", 4},
};

switch (function) {
case 0:
switch (argument) {
case 2:
if(str >= 0 && str < 4) {
strncpy_s (customStr->szString, position_values[str].szString,
sizeof(customStr->szString)-1);
customStr->iID = position_values[str].iID;
}
break;
default:
res = MSX_ERROR;
break;
}
break;
case 1:
switch (argument) {
case 4:
if(str >= 0 && str < 4) {
strncpy_s (customStr->szString, position_values[str].szString,
sizeof(customStr->szString)-1);
customStr->iID = position_values[str].iID;
}
break;
default:
res = MSX_ERROR;
break;
}
break;
case 2:
switch (argument) {
case 5:
if(str >= 0 && str < 4) {

53
strncpy_s (customStr->szString, position_values[str].szString,
sizeof(customStr->szString)-1);
customStr->iID = position_values[str].iID;
}
break;
case 6:
if(str >= 0 && str < 10) {
strncpy_s (customStr->szString, export_values[str].szString,
sizeof(customStr->szString)-1);
customStr->iID = export_values[str].iID;
}
break;
default:
res = MSX_ERROR;
break;
}
break;
default:
res = MSX_ERROR;
break;
}

return res;
}

// -----------------------------------------------------------------------------------------

BOOL __stdcall VolatilityStop (const MSXDataRec *dataRec,


const MSXDataInfoRecArgsArray *dataInfoArgs,
const MSXNumericArgsArray *numArgs,
const MSXStringArgsArray *stringArgs,
const MSXCustomArgsArray *customArgs,
MSXResultRec *output)
{
BOOL res = MSX_SUCCESS;

output->psResultArray->iFirstValid = 0;
output->psResultArray->iLastValid = -1;

/*
- stopVal = volatility data
for long positions:
- if current threshold price is LOWER than previous stop, use stopVal
(we have been stopped out, so let's have a fresh start)
- else use MAX between stopVal and its previous value
for short positions:
- if current threshold price is HIGHER than previous stop, use stopVal
(we have been stopped out, so let's have a fresh start)
- else use MIN between stopVal and its previous value
*/

int firstIndex = 0;
int lastIndex = -1;
int i=0;

const MSXDataInfoRec *thresholdPrice;


const MSXDataInfoRec *volatility;
int positionType = 0;
float currentStopVal = 0;
float previousStopVal = 0;

if (dataInfoArgs->iNRecs == 2 && customArgs->iNRecs == 1) {

thresholdPrice = dataInfoArgs->psDataInfoRecs[0];
volatility = dataInfoArgs->psDataInfoRecs[1];
positionType = customArgs->iCustomIDs[0];

firstIndex = MSXMax(thresholdPrice->iFirstValid,volatility->iFirstValid);
lastIndex = MSXMin(thresholdPrice->iLastValid,volatility->iLastValid);

if (firstIndex > 0 && lastIndex > 0


&& firstIndex >= dataRec->sClose.iFirstValid &&
lastIndex <= dataRec->sClose.iLastValid) {

// this is where the magic happens

previousStopVal = currentStopVal = 0;

54
for (i=firstIndex; i<=lastIndex ; i++) {

currentStopVal = volatility->pfValue[i];

switch(positionType) {
case 0: // long
if (thresholdPrice->pfValue[i]>=previousStopVal)
currentStopVal = MSXMax(currentStopVal,previousStopVal);
break;
case 1: //short
if (thresholdPrice->pfValue[i]<=previousStopVal)
currentStopVal = MSXMin(currentStopVal,previousStopVal);
break;
default:
{
strncpy_s (output->szExtendedError, "Undefined method argument",
sizeof(output->szExtendedError)-1);
res = MSX_ERROR; // report this as an error
}
break;

} // end switch method

output->psResultArray->pfValue[i] = currentStopVal;
previousStopVal = currentStopVal;
}
output->psResultArray->iFirstValid = firstIndex;
output->psResultArray->iLastValid = lastIndex;

} else {
output->psResultArray->iFirstValid = 0;
output->psResultArray->iLastValid = -1;
}

} else { // wrong number of arguments!


strncpy_s (output->szExtendedError, "Wrong number of arguments",
sizeof(output->szExtendedError)-1);
res = MSX_ERROR;
} // end if argument count is OK

return res;

// -----------------------------------------------------------------------------------------

BOOL __stdcall ConditionalVolatilityStop (const MSXDataRec *dataRec,


const MSXDataInfoRecArgsArray *dataInfoArgs,
const MSXNumericArgsArray *numArgs,
const MSXStringArgsArray *stringArgs,
const MSXCustomArgsArray *customArgs,
MSXResultRec *output)
{
BOOL res = MSX_SUCCESS;

output->psResultArray->iFirstValid = 0;
output->psResultArray->iLastValid = -1;

/*

for long positions:


- stopVal = If (condition) use new stop level, otherwise use volatility data
- if current threshold price is LOWER than previous stop, use stopVal
(we have been stopped out, so let's have a fresh start)
- else use MAX between stopVal and its previous value
for short positions:
- stopVal = If (condition) use new stop level, otherwise use volatility data
- if current threshold price is HIGHER than previous stop, use stopVal
(we have been stopped out, so let's have a fresh start)
- else use MIN between stopVal and its previous value
*/

int firstIndex = 0;
int lastIndex = -1;
int i=0;

55
const MSXDataInfoRec *thresholdPrice;
const MSXDataInfoRec *volatility;
const MSXDataInfoRec *condition;
const MSXDataInfoRec *newStopLevel;
int positionType = 0;
float currentStopVal = 0;
float previousStopVal = 0;
float previousCondition = 0;
float currentCondition = 0;

if (dataInfoArgs->iNRecs == 4 && customArgs->iNRecs == 1) {

thresholdPrice = dataInfoArgs->psDataInfoRecs[0];
volatility = dataInfoArgs->psDataInfoRecs[1];
condition = dataInfoArgs->psDataInfoRecs[2];
newStopLevel = dataInfoArgs->psDataInfoRecs[3];
positionType = customArgs->iCustomIDs[0];

firstIndex = MSXMax(thresholdPrice->iFirstValid,volatility->iFirstValid);
firstIndex = MSXMax(firstIndex,condition->iFirstValid);
firstIndex = MSXMax(firstIndex,newStopLevel->iFirstValid);

lastIndex = MSXMin(thresholdPrice->iLastValid,volatility->iLastValid);
lastIndex = MSXMin(lastIndex,condition->iLastValid);
lastIndex = MSXMin(lastIndex,newStopLevel->iLastValid);

if (firstIndex > 0 && lastIndex > 0


&& firstIndex >= dataRec->sClose.iFirstValid &&
lastIndex <= dataRec->sClose.iLastValid) {

// this is where the magic happens

previousStopVal = currentStopVal = 0;
previousCondition = currentCondition = 0;
for (i=firstIndex; i<=lastIndex ; i++) {

switch(positionType) {
case 0: // long
if (previousCondition==1 || condition->pfValue[i]>0)
currentCondition = 1;
else
currentCondition = 0;
if (currentCondition==1)
currentStopVal = newStopLevel->pfValue[i];
else
currentStopVal = volatility->pfValue[i];
if (thresholdPrice->pfValue[i]>=previousStopVal)
currentStopVal = MSXMax(currentStopVal,previousStopVal);
else
currentCondition = 0;
break;
case 1: //short
if (previousCondition==1 || condition->pfValue[i]>0)
currentCondition = 1;
else
currentCondition = 0;
if (currentCondition==1)
currentStopVal = newStopLevel->pfValue[i];
else
currentStopVal = volatility->pfValue[i];
if (thresholdPrice->pfValue[i]<=previousStopVal)
currentStopVal = MSXMin(currentStopVal,previousStopVal);
else
currentCondition = 0;
break;
default:
{
strncpy_s (output->szExtendedError, "Undefined method argument",
sizeof(output->szExtendedError)-1);
res = MSX_ERROR; // report this as an error
}
break;

} // end switch positionType

previousCondition = currentCondition;
output->psResultArray->pfValue[i] = currentStopVal;

56
previousStopVal = currentStopVal;
}
output->psResultArray->iFirstValid = firstIndex;
output->psResultArray->iLastValid = lastIndex;

} else {
output->psResultArray->iFirstValid = 0;
output->psResultArray->iLastValid = -1;
}

} else { // wrong number of arguments!


strncpy_s (output->szExtendedError, "Wrong number of arguments",
sizeof(output->szExtendedError)-1);
res = MSX_ERROR;
} // end if argument count is OK

return res;

// -----------------------------------------------------------------------------------------

#define ABS(x) ((x) >= 0 ? (x) : -(x))

BOOL __stdcall Trigger (const MSXDataRec *dataRec,


const MSXDataInfoRecArgsArray *dataInfoArgs,
const MSXNumericArgsArray *numArgs,
const MSXStringArgsArray *stringArgs,
const MSXCustomArgsArray *customArgs,
MSXResultRec *output)
{
BOOL res = MSX_SUCCESS;

output->psResultArray->iFirstValid = 0;
output->psResultArray->iLastValid = -1;

/*
currentState, previousState and lastEntryPrice start as 0

for each record


if previousState is 1 AND lastEntryPrice<>0
if long profit = close - lastEntryPrice; else profit = lastEntryPrice - close;
else profit = 0;
if long profitCheck = high - lastEntryPrice; else profit = lastEntryPrice - low;
stoppedGain = profitCheck>=StopGain AND stopGain<>0
stop = stop OR profit>=stoppedGain
if (stoppedGain)
exitPrice = lastEntryPrice + stopGain else exitPrice = 0
profit = stopGain

currentState = NOT(Stop) AND (Signal OR previousState)


trigger will be 1 when previousState is 0 and currentState is 1
trigger will be -1 when previousState is 1 and currentState is 0

if trigger is 1 lastEntryPrice = entryPrice


previousState = currentState
*/

int firstIndex = 0;
int lastIndex = -1;
int i=0;

const MSXDataInfoRec *entryPrice;


const MSXDataInfoRec *signal;
const MSXDataInfoRec *stop;
const MSXDataInfoRec *stopGain;
const MSXDataInfoRec *maxLoss;
float stopGainVal;
int positionType = 0;
int exportType = 0;

int trigger = 0;
int stoppedGain = 0;
int stopped = 0;
int stoppedMaxLoss = 0;

57
int previousState = 0;
int currentState = 0;
float profit = 0;
float profitCheck = 0;
float lastEntryPrice = 0;
float exitPrice = 0;
float diff = 0;

if (dataInfoArgs->iNRecs == 5 && customArgs->iNRecs == 2) {

entryPrice = dataInfoArgs->psDataInfoRecs[0];
signal = dataInfoArgs->psDataInfoRecs[1];
stop = dataInfoArgs->psDataInfoRecs[2];
stopGain = dataInfoArgs->psDataInfoRecs[3];
maxLoss = dataInfoArgs->psDataInfoRecs[4];

positionType = customArgs->iCustomIDs[0];
exportType = customArgs->iCustomIDs[1];

firstIndex = MSXMax(entryPrice->iFirstValid,signal->iFirstValid);
firstIndex = MSXMax(firstIndex,stop->iFirstValid);
firstIndex = MSXMax(firstIndex,stopGain->iFirstValid);
firstIndex = MSXMax(firstIndex,maxLoss->iFirstValid);

lastIndex = MSXMin(entryPrice->iLastValid,signal->iLastValid);
lastIndex = MSXMin(lastIndex,stop->iLastValid);
lastIndex = MSXMin(lastIndex,stopGain->iLastValid);
lastIndex = MSXMin(lastIndex,maxLoss->iLastValid);

if (firstIndex > 0 && lastIndex > 0


&& firstIndex >= dataRec->sClose.iFirstValid &&
lastIndex <= dataRec->sClose.iLastValid) {

// sweet

for (i=firstIndex; i<=lastIndex ; i++) {

profit = 0;
profitCheck = 0;
diff = 0;

switch(positionType) {
case 0: // long

if (previousState==1 && lastEntryPrice!=0) {


profit = dataRec->sClose.pfValue[i] - lastEntryPrice;
profitCheck = dataRec->sHigh.pfValue[i] - lastEntryPrice;
diff = dataRec->sLow.pfValue[i]-lastEntryPrice;
}
stopGainVal = stopGain->pfValue[i];
stoppedGain = profitCheck>=stopGainVal && stopGainVal > 0;
stopped = int(stop->pfValue[i]);

stoppedMaxLoss = maxLoss->pfValue[i]>0 && diff<0 &&


ABS(diff)>maxLoss->pfValue[i];

stopped = stopped || stoppedGain || stoppedMaxLoss;

if (stoppedGain) {
exitPrice = lastEntryPrice + stopGainVal;
if (dataRec->sOpen.pfValue[i]>exitPrice)
exitPrice = dataRec->sOpen.pfValue[i];
profit = exitPrice - lastEntryPrice;
} else {
if(stoppedMaxLoss) {
exitPrice = lastEntryPrice - maxLoss->pfValue[i];
if (dataRec->sOpen.pfValue[i]<exitPrice)
exitPrice = dataRec->sOpen.pfValue[i];
profit = exitPrice - lastEntryPrice;
} else exitPrice = 0;
}

currentState = !stopped && (int(signal->pfValue[i]) ||


previousState);
trigger = 0;
if (currentState==1 && previousState ==0) trigger = 1;
if (currentState==0 && previousState ==1) {

58
if (stoppedGain) trigger = -2; else
if (stoppedMaxLoss) trigger = -3; else trigger = -1;
}

if (trigger==1) lastEntryPrice = entryPrice->pfValue[i];


previousState = currentState;
break;
case 1: //short
if (previousState==1 && lastEntryPrice!=0) {
profit = lastEntryPrice - dataRec->sClose.pfValue[i];
profitCheck = lastEntryPrice - dataRec->sLow.pfValue[i];
diff = lastEntryPrice - dataRec->sHigh.pfValue[i];
}
stopGainVal = stopGain->pfValue[i];
stoppedGain = profitCheck>=stopGainVal && stopGainVal > 0;
stopped = int(stop->pfValue[i]);

stoppedMaxLoss = maxLoss->pfValue[i]>0 && diff<0 &&


ABS(diff)>maxLoss->pfValue[i];

stopped = stopped || stoppedGain || stoppedMaxLoss;

if (stoppedGain) {
exitPrice = lastEntryPrice - stopGainVal;
if (dataRec->sOpen.pfValue[i]<exitPrice)
exitPrice = dataRec->sOpen.pfValue[i];
profit = lastEntryPrice - exitPrice;
} else {
if(stoppedMaxLoss) {
exitPrice = lastEntryPrice + maxLoss->pfValue[i];
if (dataRec->sOpen.pfValue[i]>exitPrice)
exitPrice = dataRec->sOpen.pfValue[i];
profit = lastEntryPrice - exitPrice;
} else exitPrice = 0;
}

currentState = !stopped && (int(signal->pfValue[i]) ||


previousState);
trigger = 0;
if (currentState==1 && previousState ==0) trigger = 1;
if (currentState==0 && previousState ==1) {
if (stoppedGain) trigger = -2; else
if (stoppedMaxLoss) trigger = -3; else trigger = -1;
}

if (trigger==1) lastEntryPrice = entryPrice->pfValue[i];


previousState = currentState;
break;
default:
{
strncpy_s (output->szExtendedError, "Undefined method argument",
sizeof(output->szExtendedError)-1);
res = MSX_ERROR; // report this as an error
}
break;

} // end switch positionType

switch(exportType) {
case 0: // trigger
output->psResultArray->pfValue[i] = float(trigger);
break;
case 1: //state
output->psResultArray->pfValue[i] = float(currentState);
break;
case 2: //profit
output->psResultArray->pfValue[i] = float(profit);
break;
case 3: //entryPrice
output->psResultArray->pfValue[i] = float(lastEntryPrice);
break;
case 4: //exitPrice
output->psResultArray->pfValue[i] = float(exitPrice);
break;
default:
{
strncpy_s (output->szExtendedError, "Undefined method argument",

59
sizeof(output->szExtendedError)-1);
res = MSX_ERROR; // report this as an error
}
break;

} // end switch positionType

}
output->psResultArray->iFirstValid = firstIndex;
output->psResultArray->iLastValid = lastIndex;

} else {
output->psResultArray->iFirstValid = 0;
output->psResultArray->iLastValid = -1;
}

} else { // wrong number of arguments!


strncpy_s (output->szExtendedError, "Wrong number of arguments",
sizeof(output->szExtendedError)-1);
res = MSX_ERROR;
} // end if argument count is OK

return res;

#ifdef __cplusplus
}
#endif

60