Escolar Documentos
Profissional Documentos
Cultura Documentos
Artigo GapHiLoIndice V1.0
Artigo GapHiLoIndice V1.0
Autores: Eduardo Sanches (longwave) - eduardo@sanches.odo.br Isac Costa isac.costa@gmail.com Data: Agosto de 2008 ndice 1. Introduo ..................................................................................................................................................... 3 1.1. Motivao................................................................................................................................................ 3 1.2. Sobre este estudo ................................................................................................................................... 4 1.3. Resultado de operaes em contratos futuros de ndice Ibovespa.......................................................... 4 1.4. Produo de renda e gerao de riqueza ............................................................................................... 5 2. HiLo Activator ................................................................................................................................................ 7 2.1. Definio e Frmula ................................................................................................................................ 7 2.2. Uso do HiLo Activator como estratgia de stop mvel............................................................................. 8 2.3. Visualizao alternativa do HiLo Activator............................................................................................... 9 3. Setup: Gaps com HiLo................................................................................................................................. 12 3.1. Periodicidade ........................................................................................................................................ 12 3.2. Layout Grfico....................................................................................................................................... 12 3.3. Anlise Prvia ....................................................................................................................................... 13 3.4. Sinal de entrada e Stop Inicial............................................................................................................... 13 3.4.1. Gap sem inverso do HiLo ......................................................................................................... 13 3.4.2. Gaps com inverso do HiLo ....................................................................................................... 19 3.5. Consideraes sobre a sada do trade.................................................................................................. 24 3.5.1. HiLo Activator ............................................................................................................................. 24 3.5.2. MM10 ......................................................................................................................................... 24 3.5.3. Stop gain pr-definido ou em nveis extremos ............................................................................ 25 3.5.4. Envelopes de Volatilidade .......................................................................................................... 26 3.6. Discusses............................................................................................................................................ 27 3.6.1. Consideraes gerais sobre os testes........................................................................................ 28 3.6.2. Testes para Gap sem Inverso do HiLo ..................................................................................... 29 3.6.3. Testes para Gap com Inverso do HiLo ..................................................................................... 33 3.6.4. Gaps com HiLo........................................................................................................................... 34 3.6.5. Estratgia combinada com Slippage e Manejo de Risco ............................................................ 37 4. Consideraes finais ................................................................................................................................... 41 5. Referncias ................................................................................................................................................. 42 6. Cdigo fonte dos indicadores e exploraes para MetaStock...................................................................... 43 6.1. HiLoZone .............................................................................................................................................. 43 6.2. Longwave 1........................................................................................................................................... 43 6.3. Longwave 2........................................................................................................................................... 43 6.4. Explorao Sim longwave 12........................................................................................................... 44 6.5. Longwave 3........................................................................................................................................... 45 6.6. Longwave 4........................................................................................................................................... 45 6.7. Explorao Sim longwave 34........................................................................................................... 46 6.8. Longwave 5........................................................................................................................................... 46 6.9. Longwave 6........................................................................................................................................... 46 6.10. Explorao Sim longwave 56 ......................................................................................................... 47 6.11. Explorao Sim GapHiLo............................................................................................................... 47 6.12. Explorao Sim Gap HiLo(S) ......................................................................................................... 48 7. Ferramentas e dados utilizados nos testes.................................................................................................. 49 8. Registro dos trades simulados para cada setup .......................................................................................... 50 9. Cdigo Fonte da DLL TestHelper ................................................................................................................ 50 1
AVISO IMPORTANTE
Este artigo de autoria de Eduardo Sanches e Isac Costa. Pedimos que sua distribuio no seja realizada sem um prvio contato com os autores. As informaes deste estudo possuem cunho didtico, e baseiam-se em uma anlise de operaes simuladas sobre dados histricos em um derivativo, o mini-contrato futuro de ndice Ibovespa, negociado na Bolsa de Mercadorias e Futuros de So Paulo (BM&F). Estratgias que utilizam derivativos podem resultar em perdas patrimoniais significativas, por esta razo, recomendamos fortemente que os leitores realizem seus prprios testes, seja repetindo as simulaes aqui realizadas ou atravs de paper trading ou qualquer outro mtodo, antes de aplicar os setups discutidos em operaes reais. Rentabilidade obtida no passado no representa garantia de rentabilidade futura. Quaisquer rentabilidades apresentadas aqui so resultados obtidos atravs de simulaes sobre dados histricos. Desta forma, os autores eximem-se da responsabilidade de quaisquer decises de investimento tomadas pelos leitores, ainda que baseadas no contedo deste estudo. Ressaltamos ainda que no h, por parte dos autores, a obrigao em oferecer suporte ou esclarecimentos sobre quaisquer dvidas sobre este estudo, ainda que os mesmos possam ser encontrados nos endereos de e-mail indicados. Este estudo no objeto de nenhuma transao comercial entre os autores e os sites onde foram publicados, representando um esforo voluntrio e no remunerado dos mesmos, com o objetivo de compartilhar conhecimento sobre os mercados e tcnicas de trading. Pedimos que, quando da utilizao de qualquer indicador, explorer ou DLL produzido e apresentado aqui, o trabalho dos autores seja devidamente reconhecido.
1. Introduo
1.1. Motivao
Ao considerarmos a variao do mercado como um todo em um determinado perodo de tempo, usualmente verificamos a variao percentual do ndice que o representa, assim como a taxa de juros livre de risco (geralmente o CDI acumulado no perodo). 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 srie histrica fornecida pela Nelogica (http://www.nelogica.com.br) em seu software, ProfitChart. Para o mesmo perodo a variao do ndice Bovespa foi de 26.768 pontos (63.396 36.628) ou 73%. Ao pensarmos em utilizar uma tcnica individual de trading ou um conjunto de tcnicas, devemos nos perguntar se o resultado esperado foi superior rentabilidade dos ndices de referncia no perodo, o que corresponderia a uma estratgia de buy and hold nestes ndices. Exemplos destas operaes mais fceis seriam: posio comprada no contrato de ndice futuro, rolando para frente a cada novo vencimento, ou posio em um fundo de renda fixa com rentabilidade o mais prxima possvel do CDI ou montagem de uma carteira com correlao perfeita com o ndice Bovespa. Ser que o mtodo que estamos utilizando supera tais rentabilidades? Ser que vale a pena o esforo de acompanhar o mercado diariamente, conviver com o desgaste psicol(futo )5s5dasware,ou
Buscamos apresentar as tcnicas visando diminuir a subjetividade na tomada de deciso. Para cada tcnica so discutidos: Periodicidade: prazo operacional para as operaes Layout grfico: tipo de grfico e indicadores a serem inseridos e configurados Anlise prvia: critrios gerais a serem observados antes da execuo dos trades Sinal de entrada: critrios grficos para a entrada em um trade, tamanho da posio e stop inicial Sinal de sada: critrios grficos para a finalizao de uma posio Discusses: resultados sobre dados histricos, limitaes e comentrios gerais sobre sua utilizao
As tcnicas aqui apresentadas so conjecturas dos autores feitas a partir de sua prpria experincia e da experincia de outros traders com os quais estivemos em contato nos ltimos dois anos. A contribuio de outros autores e destes traders ser devidamente reconhecida em cada caso.
De forma resumida, o resultado financeiro de uma operao em mini-ndice pode ser calculado por: Resultado = Quantidade x (Valor Final Valor Inicial) / 5 Para operaes de compra, a quantidade positiva e para operaes de venda, a quantidade negativa. Os valores inicial e final representam, respectivamente, os valores de negociao na abertura e no encerramento da posio. Assim, um indivduo que abrir uma posio de compra de 8 mini-contratos a 67.000 pontos e encerrar esta posio a 67.350 pontos ter um resultado de: Resultado = 8 x (67.350-67.000) / 5 = 560 reais (Lucro) Se outro indivduo abrir uma posio de venda de 13 mini-contratos a 67.000 pontos e encerrar esta posio a 67.350 pontos ter um resultado de: Resultado = - 13 x (67.350-67.000) / 5 = - 910 (Prejuzo) Se fizermos com que os tamanhos das posies sejam mltiplos de 5, o clculo fica mais fcil de ser executado. Para cada 5 mini-contratos, o nmero de pontos da operao equivale ao resultado financeiro. Dessa forma, poderemos ver, de forma idntica, qual o nmero lquido de pontos e reais fornecido por cada tcnica em um determinado perodo.
amplificar tanto os ganhos quanto as perdas, e um dos principais fatores que atraem especuladores em especial day traders - para derivativos. Se considerarmos uma estratgia que propicie um resultado lquido de 100 pontos por prego e considerarmos que estaremos atuando em 10 preges em cada ms, teramos um resultado de 1.000 pontos no ms. Se mantivermos uma conta margem com saldo de R$ 20.000,00 e operarmos posies constantes de 5 mini-contratos, utilizando R$ 10.000,00 para margem e o restante como reserva de segurana para trades negativos, teramos um resultado financeiro de R$ 1.000,00 sobre os R$ 20.000,00, um percentual de 5% sobre a margem no perodo em questo. Desta forma, estamos interessados em tcnicas cujos resultados sejam mdias constantes e positivas para cada prego e faam com que o capital no seja depreciado a ponto de no permitir ao menos a abertura da posio mnima. No exemplo anterior, se tivermos perdas consecutivas que faam com que o capital caia abaixo de R$ 10.000,00 no poderemos abrir a posio constante de 5 mini-contratos. Em termos tcnicos, estaremos interessados em setups que gerem resultados lquidos de, ao menos 100 pontos por trade e que tenham um drawdown mximo que fique o mais longe possvel de 20% sobre o capital inicial em cada perodo. Veja que no necessariamente buscamos setups com mais de 70 ou 80% de acertos, mas sim aqueles cuja diferena entre o resultado mdio dos trades positivos e o resultado mdio dos trades negativos seja positiva e superior a 100 pontos. Uma limitao prtica desta abordagem consiste no fato de que, aps uma seqncia de trades negativos, mesmo que com pequenas perdas, o operador pode perder a confiana no seu mtodo e abandon-lo, justamente antes da realizao do trade positivo que compensaria todas as perdas anteriores e geraria lucro. Outra limitao representada pelo fato de que operadores humanos no necessariamente iro executar todos os sinais fornecidos por um setup, havendo o risco de que trades vitoriosos sejam perdidos e os lucros potenciais no sejam realizados. Uma observao importante Embora a alavancagem proporcionada pelo mini-ndice permita estes ganhos potenciais considerveis, a no perfeita execuo das tcnicas, o fator probabilstico das mesmas e as diversas barreiras psicolgicas enfrentadas pela maioria dos participantes dos mercados impedem que estes resultados potenciais sejam efetivamente realizados. O objetivo deste artigo no iniciar uma cruzada pelo Santo Graal dos trades, mas sim discutir mtodos que possam ser executados quase que de uma forma algortmica, que sejam de visualizao e execuo relativamente simples e que se encaixem nos requisitos de performance mencionados anteriormente.
2. HiLo Activator
2.1. Definio e Frmula
Nesta seo apresentamos o HiLo Activator, um dos indicadores fundamentais para os setups analisados neste artigo. O HiLo Activator, tambm 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 contedo deste artigo foi publicado novamente no The Fibonacci Trader Journal e seu contedo est disponvel online (vide seo Referncias). Em geral, as mdias mveis utilizam preos de fechamento em seu clculo. A proposta do HiLo Activator, ao qual nos referenciaremos a partir daqui simplesmente por HiLo, consiste em observar duas mdias mveis, a das mximas e a das mnimas dos N perodos anteriores, com deslocamento de 1 perodo. Caso o fechamento tenha ocorrido acima da mdia das mximas, entramos em uma zona positiva ou comprada. Caso o fechamento ocorra abaixo da mdia das mnimas, temos a zona inversa, negativa ou vendida. Caso estejamos comprados, os valores da mdia das mnimas representam patamares que, se perdidos, indicam fraqueza no movimento, representando, dessa forma, pontos de sada do trade. No caso de estarmos vendidos, a mdia das mximas representa um ponto de referncia para sada do trade, de forma anloga. Um cuidado especial: a mdia com a qual comparamos o valor de fechamento do candle a mdia de mximas e mnimas dos N perodos anteriores. Nos softwares grficos em geral, o valor de qualquer mdia mvel inclui para um determinado candle inclui os valores deste candle em seu clculo. No caso do HiLo, devemos utilizar a MM fornecida pelo software para o perodo anterior, desta forma, j teremos os dois valores que iro servir de referncia antes que o candle seja formado. Figura 2.1. HiLo Activator no grfico dirio da srie histrica do mini-ndice
Os valores das mdias mveis so desenhados de forma pouco usual, como patamares, conectados a cada dia, criando a impresso de estarmos vendo uma escada ascendente ou descendente de stops mveis. 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 perodo anterior, temos um possvel ponto de sada do trade. Em geral, utiliza-se o HiLo de 3 perodos, isto , as mdias mveis de mximas e mnimas so mdias mveis aritmticas de 3 perodos. Nos setups apresentados neste artigo, porm, utilizaremos HiLos de perodos alternativos, como o de 10 perodos. No software Metastock, da Equis International o HiLo pode ser criado como um indicador personalizado, utilizando-se a seguinte frmula: 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; Porm, a visualizao ligeiramente diferente da indicada na Figura 2.1, no ficando claras as zonas compradas e vendidas como no software ProfitChart, da Nelogica. Por esta razo, criamos um indicador chamado HiLoZone para o Metastock, que ser utilizado nas simulaes. 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;
Figura 2.2. HiLo no grfico semanal do mini-ndice Indicadores semelhantes ao HiLo quanto ao uso (stop mvel) so o VSS, criado por Joe Ross, e o SAR parablico, criado por Welles Wilder.
Observe o efeito resultante na Figura 2.3.2. Cria-se um envelope com as duas mdias e os rompimentos destes envelopes indicam sinais de compra ou venda, sejam estes sinais que iniciem um trade ou sinais de stop para posies originalmente inversas. Em grficos intraday, onde h uma maior variao nas tendncias dos preos do que em grficos de periodicidade maior, a visualizao do HiLo como mdias permite uma 10
tcnica 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 tambm insira o HiLo Activator no mesmo grfico para verificar a conformidade dos valores com as mdias mveis e a mudana de zona cada vez que o fechamento fecha fora do envelope de mdias. A sugesto da visualizao do HiLo como mdias foi uma idia do trader Roger Batt, tambm conhecido como Frances. Nas sees a seguir iremos analisar o uso do HiLo com outros padres grficos para definio de critrios de entrada e sada de trades.
11
12
Os conceitos de gap de rea, exausto, medida e fuga podem ser aplicados, desde que seja analisada sua posio dentro da tendncia descrita no grfico de 30 minutos. A tcnica proposta aqui, porm, no se baseia nas tticas 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 histricos, no consideramos o tipo de gap e a efetivao do trade ou no conforme o resultado desta anlise. Acreditamos que este pode ser um filtro adicional a ser aplicado pelo trader quando da utilizao manual do setup.
Caso estas condies sejam satisfeitas, entramos no rompimento da mxima dos primeiros quatro candles, sem esperar fechamento, com stop inicial abaixo da mnima do candle que originou a entrada. A sada do trade ocorrer se houver um fechamento abaixo da mdia mvel simples de 10 perodos das mnimas, OU em stop gain ou perda mxima (veja comentrios a seguir) OU no final do dia. O fechamento abaixo da MM10 das mnimas equivale a uma mudana de zona de HiLo comprado para HiLo vendido. Na ponta comprada, testes realizados indicaram que o uso da lgica de stop gain ou perda mxima no melhorou a performance significativamente. Teremos uma entrada na ponta de VENDA se: a) b) c) d) Houver um gap de baixa (superior a 200 pontos) O HiLo Activator(10) estiver sempre vendido A mxima do dia estiver no mximo 100 pontos abaixo do fechamento do dia anterior Ocorrer a perda da mnima dos primeiros quatro candles (primeiras duas horas de prego) 13
e) No ter ocorrido um sinal de compra no mesmo dia (apenas 1 trade por dia) Na presena destas condies, a entrada ocorre na perda da mnima dos primeiros quatro candles, sem esperar fechamento, com stop inicial acima da mxima do candle que originou a entrada. A sada do trade ocorrer se houver um fechamento acima da mdia mvel simples de 10 perodos das mximas, OU em stop gain ou perda mxima OU no final do dia. O fechamento acima da MM10 das mximas equivale a uma mudana 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 lgica do stop gain e da perda mxima? Na ausncia de gaps, se o resultado do trade atinge o valor de perda mxima 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 preos atingirem 65.500, o trade finalizado. Porm, havendo um gap, se o novo candle abre acima de 65.500, suponhamos 65.800, samos no preo de abertura deste candle. O raciocnio para a perda mxima anlogo. A principal diferena que quando os preos andam contra a entrada j na mesma barra um valor superior perda mxima, a sada ocorre na abertura do candle seguinte. Para programar esta e outras lgicas adicionais, criamos uma DLL para o Metastock, utilizando o Metastock Developers Kit, denominada TestHelper.DLL. Disponibilizamos no final deste documento o cdigo fonte desta DLL para que a lgica de stop gain e perda mxima seja visualizadas. Veja tambm a seo Ferramentas e dados utilizados nos testes para maiores informaes.
Vamos analisar alguns exemplos para os casos descritos aqui. Observe que estes exemplos so meramente ilustrativos e no 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 preos ser semelhante, devido preservao do momentum de um dia para o outro e a confirmao deste fato via HiLo Activator, no violao do gap e/ou e rompimento de range.
14
Observe a entrada no rompimento do range, o stop mvel da MM10 das mnimas e a sada no final do prego, devido ao fato de o stop no ter sido acionado. Esta seria uma configurao perfeita do setup na ponta comprada. Vejamos um exemplo de uma operao mal-sucedida com este setup.
15
Veja a entrada no rompimento do range dos primeiros quatro candles. Infelizmente o setup gerou uma entrada prxima mxima do dia, e os preos recuaram at que ocorreu um fechamento abaixo da mdia mvel das mnimas, resultando em uma perda de pouco mais de 300 pontos. Caso o fechamento ocorresse abaixo do stop inicial, este deveria ser usado como preo de sada (mnima do candle que iniciou a entrada menos 200 pontos). Uma observao importante: sabemos que o valor mnimo de variao do contrato futuro de ndice de 5 pontos, porm veremos em algumas figuras e no prprio resultado da simulao, valores tais como 65.733 ou 55.418. Isto se deve ao fato de que a srie histrica 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
Teria sido a sada no stop gain precoce? Vemos que, para este trade, o mercado andou um pouco mais. Porm, veremos que, estatisticamente, a presena de stop gain para trades na ponta vendida melhora drasticamente a performance. Fica a critrio do leitor o desenvolvimento de estratgias de sada alternativas s aqui apresentadas. No prximo exemplo, veremos uma operao mal-sucedida com este setup. O ponto de venda foi prximo mnima do dia, e os preos andaram contra o trade at que ocorreu um fechamento acima da mdia mvel de 10 perodos das mximas, resultando em uma perda de cerca de 780 pontos.
17
Achamos fundamental mostrar exemplos de situaes nas quais o setup falhou. Vemos em muitos livros, apenas exemplos bem escolhidos de situaes nas quais o setup em discusso fez um trade perfeito, o que geralmente induz os leitores a acreditarem em tcnicas milagrosas, dada sua tradicional assimetria de expectativas entre ganhos e perdas e a lei dos pequenos nmeros. Na opinio dos autores, este tipo de conduta no contribui para a reputao dos analistas tcnicos que, infelizmente, so colocados no mesmo nvel que vendedores de idias de ganhos fceis nos mercados de renda varivel. Perceba que neste setup no estamos operando contra o gap, mas sim fazendo uma aposta direcional definida pela permanncia da zona do HiLo e a no violao do gap, seguida ou no de rompimento a favor da direo do mesmo. Vamos agora analisar uma situao um pouco diferente, na qual ocorre uma mudana de zona do HiLo, sinalizando que a direo do movimento anterior poder ser invertida.
18
19
Exemplo 3.4.2.1 Operao bem-sucedida de gap de alta e reverso do HiLo de compra para venda
A entrada se deu na penetrao dos preos na mdia mvel das mnimas de 10 perodos, sendo que ali os preos estavam trabalhando na mnima do dia. A sada se deu no fechamento do candle cuja mnima foi menor que a mnima anterior e o lucro apurado (entrada fechamento) foi superior a 300 pontos.
20
Exemplo 3.4.2.2 Operao mal-sucedida de gap de alta e reverso do HiLo de compra para venda
A entrada se deu apenas quando a mnima do dia foi perdida. A sada ocorreu quando houve um repique de 400 pontos a partir do ponto de entrada, na perda mxima.
21
Exemplo 3.4.2.3 Operao bem-sucedida de gap de baixa e reverso do HiLo de venda para compra
A entrada ocorreu na penetrao da mdia mvel das mximas de 10 perodos e a sada via stop gain de 500 pontos.
22
Exemplo 3.4.2.4 Operao mal-sucedida de gap de baixa e reverso do HiLo de venda para compra
Aqui, a entrada se deu no rompimento da mdia mvel das mximas de 10 perodos. A sada se deu na perda mxima, programada em 300 pontos, alguns candles depois. Uma vez apresentados os setups, vamos discutir brevemente sobre as diversas alternativas de critrios de sada e, posteriormente, apresentar os resultados obtidos para a programao das regras aqui discutidas sobre uma base de dados de 2 anos da srie histrica de mini-contratos futuros de ndice Ibovespa.
23
Vamos analisar cada uma destas opes. O mais importante que existe um trade-off entre permanecer mais tempo no trade para tentar obter o mximo do movimento, com uma maior exposio a inverses na sua direo versus sair rapidamente e garantir o lucro o mais rpido possvel, abrindo mo de ganhos adicionais. Vale lembrar que estamos falando de day trading, portanto no estamos interessados em carregar posies de um dia para outro e temos apenas 16 candles para cada prego em um grfico de 30 minutos. Cada um deve encontrar o ponto com o qual se sente mais vontade para sair do trade, porm cada escolha ir impactar significativamente na rentabilidade do sistema ao longo do tempo.
3.5.2. MM10
Uma das alternativas seria buscar um indicador que no fique to afastado dos preos quanto o HiLo(10), como, por exemplo, a MM10. Em geral a MM10 e o HiLo(10) andam prximos, mas quando o movimento acelerado a MM10 oferece uma proteo 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 posies compradas e vendidas, respectivamente.
24
Figura 3.5.2.1. HiLo(10) versus MM10 como stop mvel O problema desta abordagem que, quanto mais prximos deixamos o stop mvel dos preos atuais, maior a probabilidade de sermos estopados e deixar o movimento. H vezes em que estamos mais interessados em navegar por toda a tendncia do que aproveitar cada perna do movimento individualmente. Esta uma deciso que depende muito do estilo pessoal de cada trader.
25
PP = (High + Low + Close)/3 S2 = PP (High-Low) R2 = PP + (High-Low) Estes nveis usualmente correspondem a mximas e mnimas de um determinado prego, mas podem ser (e so) ultrapassados com alguma freqncia. O importante aqui ter um sentimento de que os preos j andaram bastante e melhor ter precauo para proteger os lucros da melhor forma possvel. Uma alternativa para detectar nveis extremos no intraday consiste em adicionar e subtrair 1 True Range ao preo de abertura. O True Range de um determinado perodo consiste em somar a amplitude deste perodo (mxima mnima) com um eventual gap do perodo anterior. Em caso de gap de alta, adicionamos amplitude a diferena entre a mnima do perodo atual e o fechamento anterior. Em caso de gap de baixa, adicionamos amplitude a diferena entre o fechamento anterior e a mxima do perodo atual.
26
3.6. Discusses
Antes de iniciarmos a discusso da validade estatstica do setup, apresentamos um breve resumo de tudo o que foi discutido at aqui:
Anlise Prvia Gap sem inverso de HiLo Determinar se o gap em questo possui MAIOR ou MENOR probabilidade de ser FECHADO, analisando a tendncia do grfico e classificando o tipo de gap. Analisar a tendncia prvia dos ltimos preges pela posio relativa dos preos e a MM10 e topos e fundos ascendentes ou descendentes
Gap de Alta com HiLo Comprado COMPRA: a) Houver um gap de alta (superior a 200 pontos) b) O HiLo Activator(10) estiver sempre comprado, desde a abertura c) A mnima do dia estiver no mximo 100 pontos acima do fechamento do dia anterior d) Ocorrer o rompimento da mxima dos primeiros quatro candles (primeiras duas horas de prego) e) No ter ocorrido um sinal de compra no mesmo dia (apenas 1 trade por dia) Stop inicial 200 pontos abaixo da mnima do candle que originou a entrada A sada do trade ocorrer se houver: um fechamento abaixo da mdia mvel simples de 10 perodos das mnimas 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 mxima do dia estiver no mximo 100 pontos abaixo do fechamento do dia anterior d) Ocorrer a perda da mnima dos primeiros quatro candles (primeiras duas horas de prego) e) No ter ocorrido um sinal de compra no mesmo dia (apenas 1 trade por dia) Stop inicial 200 pontos acima da mxima do candle que originou a entrada A sada do trade ocorrer se houver: Gap com inverso de HiLo um fechamento acima da mdia mvel simples de 10 perodos das mximas stop gain de 700 pontos no final do dia
Gap de Baixa com Inverso de HiLo para Compra - COMPRA: a) Gap de baixa (acima de 200 pontos) b) Mudana de zona do HiLo de vendido para comprado (ou penetrao de preo acima da mdia mvel das mximas de 10 perodos) c) Preos andando na mxima do dia Stop inicial 200 pontos abaixo da mnima do candle que gerou a entrada. Sada quando: fechar abaixo do stop inicial fechar abaixo da mdia das mnimas de 10 perodos stop gain de 500 pontos perda mxima de 300 pontos no final do dia
Gap de Alta com Inverso de HiLo para Venda - VENDA: a) Gap de alta (acima de 200 pontos) b) Mudana de zona do HiLo de comprado para vendido (ou penetrao de preo abaixo da mdia mvel das mnimas de 10 perodos) c) Preos andando na mnima do dia Stop inicial 200 pontos acima da mxima do candle que gerou a entrada. Sada quando: fechar abaixo do stop inicial fechar acima da mdia das mnimas de 10 perodos perda mxima de 400 pontos
27
lucro do trade estiver acima de 300 pontos e mxima do candle menor que mxima anterior no final do dia
As informaes apresentadas anteriormente foram codificadas em diversos indicadores. Na seo Cdigo fonte dos indicadores e exploraes para MetaStock possvel encontrar este cdigo e qual a lgica que foi utilizada para gerar cada informao. Depois de criados os indicadores, utilizamos o plug-in do TradeSim para o MetaStock, criando uma explorao que ir navegar por um ou mais ativos especificados e ir criar um arquivo com extenso .trb em uma pasta chamada C:\TradeSimData. Neste arquivo ficam registrados todos os trades identificados pela explorao. Uma vez criado este arquivo, basta ir ao TradeSim e abri-lo. Estamos interessados no nmero de pontos que cada setup capaz de gerar em um determinado perodo de tempo. Por esta razo, iremos utilizar sempre uma posio 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 tambm uma corretagem igual a R$ 1,00 por mini (preo usual de corretagem de minis para day trade). Desta forma, os parmetros a serem utilizados na tela Trade Parameters do TradeSim so:
Trade Parameters
Initial Capital: Portfolio Limit: Maximum number of open positions: Position Size Model: Trade Size ($ value): Pyramid profits: Transaction cost per share/contract (Trade Entry): Transaction cost per share/contract (Trade Exit): Initial Margin: Point Value: R$ 50.000,00 100,00% 1 Equal Dollar Units R$ 10.000,00 No R$ 5,00 R$ 5,00 R$ 10.000,00 R$ 1,00
Trade Preferences
Trading Instrument: Break Even Trades: Trade Position Type: Entry Order Type: Exit Order Type: Minimum Trade Size: Accept Partial Trades: Volume Filter: Pyramid Trades: Use Level Zero trades only: Commodities Process separately Process all trades Default Order Default Order R$ 0,00 No Ignore Volume Information No Yes
Configurados os parmetros, utilizamos a opo Backtest para simular a execuo de todos os trades. Esta opo 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 no h conflitos entre os trades de cada sistema testado. Caso tivssemos vrios ativos ou setups que gerassem situaes nas quais tivssemos que escolher entre diferentes entradas possveis, a melhor opo a ser utilizada a Simulao de Monte Carlo disponvel na verso Enterprise do TradeSim. Atravs desta opo, possvel fazer testes exaustivos e gerar diferentes trajetrias de trades, nas quais h um critrio aleatrio de seleo de entradas quando mais de uma possvel. Neste caso, os resultados so apresentados como mdias das diversas simulaes, e tambm fornecido o desvio-padro de cada parmetro estimado. Por fim, vamos recordar alguns dados fornecidos logo no incio 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 srie histrica fornecida pela Nelogica (http://www.nelogica.com.br) em seu software, ProfitChart. Para o mesmo perodo a variao do ndice Bovespa foi de 26.768 pontos (63.396 36.628) ou 73%. Estes sero os benchmarks para comparao do resultado dos setups.
Vale lembrar que na ponta vendida definimos stop gain em 700 pontos. Observamos que, atuando em 98 (19,7%) dos 498 preges do perodo, 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 frmula aproximada ((1+39,86%)^(1/498)-1)/((1+25,79%)^(1/498)-1). Uma considerao importante que neste teste no foi considerado o efeito de slippage. Na prtica, quando temos um rompimento como o indicado pelo setup, dificilmente iremos conseguir entrar no exato preo da resistncia ou suporte cuja violao aguardamos. Usualmente, no caso do ndice, teremos um spread variando entre 50 e 100 pontos. Para posies 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 reverso. As figuras a seguir mostrar um histograma indicando o nmero de trades para cada faixa de rentabilidade e a evoluo da curva de capital ao longo do tempo, indicando os perodos de drawdown. Infelizmente, o TradeSim mostra os resultados apenas de forma percentual, mas podemos verificar que o maior nmero de trades na faixa entre 6 e 7% deve-se lgica de stop gain na ponta vendida. 29
30
A ttulo de curiosidade, apresentamos os resultados do setup sem o uso de stop gain na ponta vendida.
Sem stop gain e perda mxima Rentabilidade Nmero de trades % de acertos Maior ganho Maior perda Mximo drawdown absoluto Mximo drawdown relativo Ponta comprada 11.222 57 64,91% 1.674 (626) Ponta vendida 3.728 41 51,22% 1.236 (818) -1.863 -3,65% Total 14.950 98 59,18% 1.674 (818)
Aps ter realizado esta simulao, verificamos os trades individualmente e observamos que no caso de operaes de venda, o mercado geralmente anda bem rpido quando cai, mas tambm repica forte aps encontrar um suporte forte ou no final de um dia predominantemente baixista. Aguardar um fechamento acima da mdia mvel das mximas (stop mvel que propusemos) uma estratgia que, por vezes, deixa boa parte do movimento para o mercado, porque os preos tendem a se afastar bastante destas mdias 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 prtica, ao invs de a posio ser automaticamente encerrada quando o trade andar 700 pontos, seja colocado neste preo um stop, permitindo que seja possvel seguir um pouco mais no movimento. Eliminao do stop mvel na mdia das mximas/mnimas Tendo em vista a observao acima sobre o uso da mdia mvel como stop, testamos tambm uma estratgia alternativa para sada do trade. Para ambas as pontas, eliminamos este critrio de sada. E para a ponta comprada tambm eliminamos o critrio de fechamento abaixo do stop inicial, deixando apenas um controle de perda mxima em 800 pontos. Desta forma os critrios de sada so: 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 variao do setup foi implementada atravs dos indicadores longwave 3 e longwave 4, e da explorao Sim longwave 34, cujo cdigo est disponvel na seo Cdigo fonte dos indicadores e exploraes para MetaStock.
Gap sem reverso do HiLo (2) Rentabilidade Nmero de trades % de acertos Maior ganho Maior perda Mximo drawdown absoluto Mximo drawdown relativo Ponta comprada 11.889 57 64,91% 1.674 (810) Ponta vendida 9.832 41 68,29% 690 (818) -2.391 -4,69% Total 21.721 98 66,33% 1.674 (818)
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 tolerncia a perdas na ponta comprada (sem stop mvel e perda mxima de 800 pontos) fez com que o mximo drawdown piorasse um pouco, sendo cerca de 500 pontos maior que o obtido com o uso do stop mvel. Nas figuras a seguir vemos a nova distribuio de rentabilidade dos trades e a evoluo dos lucros ao longo do tempo. 31
Figura 3.6.2.4. Evoluo dos resultados ao longo do tempo, sem stop mvel
32
Vale lembrar que na ponta comprada, temos stop gain de 500 pontos e perda mxima de 300 pontos. Na ponta vendida, temos perda mxima de 400 pontos e sada via stop gain quando o fechamento de um candle menos o preo de entrada for superior a 300 pontos e a mxima deste candle for menor que a mxima do candle anterior. Dos 489 preges no perodo, este setup gerou entrada em 182 deles ou 37% dos dias. Sua performance no perodo foi de 74% do movimento do prprio ndice para uma posio sinttica de Buy and Hold na srie histrica e 117% do CDI no perodo. Consideramos este um setup complementar ao Gap sem Inverso de HiLo, de modo que podemos criar um trading system combinando os dois setups. Vamos discutir os resultados combinados na prxima seo. Figura 3.6.3.1. Distribuio de rentabilidade dos trades
33
Este resultado equivale a 178% da variao de 20.827 pontos do prprio ndice e 242% do CDI no perodo. Porm, para uma estimativa mais realista e para uma anlise de drawdown, devemos analisar o resultado da simulao de Monte Carlo, e tambm inserir um modelo de slippage que aproxime os valores de entrada de pontos mais prximos de desvios devido atuao humana. A figura a seguir mostra o nmero de trades para cada faixa de rentabilidade.
34
Sem considerar slippage, o resultado da simulao de Monte Carlo para as duas estratgias combinadas no perodo, mantendo-se uma posio constante de 5 mini-contratos e capital inicial de R$ 50.000,00:
Gap Com HiLo Rentabilidade Desvio Padro % de acertos Drawdown absoluto Drawdown relativo Nmero de simulaes Trades executados por simulao Mximo 46.914 60,85% (2.608) -4,98% Mdio 40.877 2.132 58,91% (2.401) -4,31% 2.000 258 Mnimo 34.945 56,98% (1.942) -3,70%
Perceba que em cada simulao foram escolhidos 258 trades do total de 280, pois 22 foram considerados como entradas conflitantes. O grfico a seguir mostra o resultado ms a ms para uma simulao.
35
Perceba que houve 4 meses negativos nos 24 considerados no perodo. O resultado financeiro apresentado equivale ao nmero de pontos do setup, pois consideramos uma posio fixa de 5 mini-contratos. A figura a seguir mostra a evoluo dos lucros ao longo do tempo. Note que esta figura uma combinao das curvas de evoluo apresentadas nas sees anteriores. Figura 3.6.4.3. Evoluo dos resultados ao longo do tempo para uma simulao
36
Podemos melhorar o resultado financeiro se modificarmos a lgica de dimensionamento da posio. Porm, antes de fazermos isso, vamos considerar um modelo de slippage no qual iremos somar um nmero entre 0 e 100 a cada entrada, sendo este nmero escolhido aleatoriamente. Para o preo de sada, 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 sada. Na prtica, em uma operao de compra estamos entrando at 100 pontos mais caro e saindo at 50 pontos mais barato. O anlogo vale para a venda. Para isto, utilizamos a funo Rand disponvel no plug-in do TradeSim para o MetaStock e criamos uma explorao denominada Sim GapHiLo(S), na qual cada entrada e sada ser afetada por este valor. O resultado dos backtests para este modelo foi:
Gap com HiLo (Slippage) Rentabilidade Nmero de trades % de acertos Maior ganho Maior perda Ponta comprada 11.784 146 57,53% 1.538 (905) Ponta vendida 6.328 134 53,73% 1.289 (902) Total 18.113 280 55,71% 1.538 (905)
Perceba que, se utilizarmos como referncia o valor mdio de lucro obtido na simulao de Monte Carlo, teremos feito 111,2% do movimento do ndice no perodo e 46% sobre o capital, ou 165% do CDI. Com a insero do slippage, j era de se esperar um drawdown maior que o observado nas simulaes anteriores.
37
Trade Parameters
Initial Capital: Portfolio Limit: Maximum number of open positions: Position Size Model: Percentage of capital risked per trade: Position size limit: Portfolio Heat: Pyramid profits: Transaction cost per share/contract (Trade Entry): Transaction cost per share/contract (Trade Exit): Initial Margin: Point Value: R$ 50.000,00 100,00% 1 Fixed Percent Risk 2,00% 100,00% 20,00% No R$ 5,00 R$ 5,00 R$ 10.000,00 R$ 1,00
Trade Preferences
Trading Instrument: Break Even Trades: Trade Position Type: Entry Order Type: Exit Order Type: Minimum Trade Size: Accept Partial Trades: Volume Filter: Pyramid Trades: Use Level Zero trades only: Commodities Process separately Process all trades Default Order Default Order R$ 0,00 No Ignore Volume Information No Yes
Perceba que o drawdown agora no mais interpretado em pontos, mas sim financeiramente. O mximo drawdown relativo foi uma perda de 18%. A rentabilidade mdia sobre o valor inicial de R$ 50.000,00 foi de 47.950, ou seja 95%, contra 48% da variao do contrato futuro de mini-ndice e 73% da variao do ndice vista. A estratgia rendeu 293% do CDI no perodo. Nosso objetivo aqui, ao apresentar estes dados, de que os critrios de sada e a regra para dimensionamento da posio so to importantes quando o critrio de entrada. E geralmente quando procuramos um setup, focamos apenas na regra de entrada. Sem os critrios de stop gain, perda mxima e sem a lgica de money management indicada, seria praticamente invivel que os mtodos apresentados gerassem algum lucro. Apresentamos a seguir alguns grficos que mostram os resultados para uma das simulaes.
38
Figura 3.6.5.1. Evoluo dos resultados ao longo do tempo para uma simulao
39
40
4. Consideraes finais
Recordamos que este estudo analisou as tcnicas propostas por um perodo 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 histricos. Para que cada tcnica seja utilizada manualmente, o trader deve fazer os seus prprios testes, verificar os piores trades possveis (vide a lista de trades no final deste texto) e como ele se comportaria em cada situao. Alm disso, importante testar cada setup como o mercado em movimento por um perodo de tempo, seja com posies pequenas ou via paper trading. Encorajamos o leitor a navegar pelos trades realizados e interpretar possveis diferenas entre os valores registrados pelo simulador e os valores que seriam resultantes da atuao de um trader humano. Caso o leitor encontre alguma inconsistncia, por favor entre em contato com os autores, que verificaremos na medida do possvel. Observe que boa parte dos bons resultados foi obtida graas a estratgias alternativas de sada, especialmente critrios de stop gain e perda mxima. Por vezes, somos tentados pela ganncia a no seguir este tipo de regra. Achamos que o mercado vai voltar aos preos 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 validao contra dados histricos nos ajuda a ter uma confiana adicional. Porm, no final, o verdadeiro lucro ir depender do nosso nvel de disciplina. Verificamos, ainda, que o uso de uma regra de dimensionamento de posio 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 no simplesmente uma regra de entrada, mas tambm um conjunto de critrios de sada e de regras de manejo de risco. Simulaes sobre dados histricos podem nos ajudar a identificar quais os melhores parmetros a serem utilizados.
41
5. Referncias
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.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) 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); AND
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) 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); AND
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", SHORT, EntryTrigger2, EntryPrice2, InitialStop2, ExitTrigger2, { { { { { { filename }
short positions } entry criteria } entry price } initial stop loss } exit criteria }
44
ExitPrice2, CONTINUE);
{ exit price }
6.5. Longwave 3
Gap de Alta com HiLo Comprado, com sada via perda mxima ou no final do dia apenas. O stop inicial e o stop mvel 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) 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; AND
6.6. Longwave 4
Gap de Baixa com HiLo Vendido, com sada via stop gain, stop inicial ou stop no final do dia. O stop mvel 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) 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); AND
45
Entry:=Trigger>0; Exit:=Trigger<0;
6.8. Longwave 5
Gap de Baixa com Inverso 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 Inverso 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 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); OR C>Ref(Mov(H,10,S),-1);
47
48
Sim GapHiLo.trb
Sim GapHiLo(S).trb
49
#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] [a1] [a2] [a3] [a4] [a5] [a6] EntryPrice(DataArray): the entry price to be used for every entry signal. Signal(DataArray): 1 for entry, 0 for no entry. Stop(DataArray): 1 for stop, 0 for no stop. StopGain(DataArray): value to be used for stop gain, use 0 to disable. MaxLoss(DataArray): maximum loss accepted, use <=0 to disable. Position (CustomString): can be "LONG", "L", "SHORT" or "S". 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; }
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 int int int trigger = 0; stoppedGain = 0; stopped = 0; 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 firstIndex firstIndex firstIndex lastIndex lastIndex lastIndex lastIndex = = = = = = = = MSXMax(entryPrice->iFirstValid,signal->iFirstValid); MSXMax(firstIndex,stop->iFirstValid); MSXMax(firstIndex,stopGain->iFirstValid); MSXMax(firstIndex,maxLoss->iFirstValid); MSXMin(entryPrice->iLastValid,signal->iLastValid); MSXMin(lastIndex,stop->iLastValid); MSXMin(lastIndex,stopGain->iLastValid); 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; }
60