Ordens e Administração de Trade
Introdução
Esta seção visa apresentar trechos de códigos com exemplos de envio de ordens e administração de trade utilizando técnicas de stoploss (fixo, móvel, breakeven) e take profit.
Você pode acessar os Snippets diretamente pelo menu lateral direito, ou fazendo CRL+F (CTRL+L) para localizar algum texto específico na página, uma vez que o conteúdo tende a crescer ao longo do tempo, dificultando a navegação pelo menu.
Caso tenham sugestões de código para acrescentar à lista, gentileza deixar o código nos comentários com o link para seu perfil em rede social (para devido crédito de autoria).
Snippets
Como limitar a quantidade de trades por dia
O código abaixo apresenta a funcionalidade em código fonte para limitar a quantidade de trades realizados pela sua estratégia/ robô (constante cQtdeMaxOperacoesNoDia).
Apesar do Módulo de Automação possui um limite de perda e ganho diário, ele não possui esta funcionalidade. Idealmente, a Nelogica deveria disponbilizar funções para verificação do resultado bruto alcançado até o momento para permitir outras forma de gestão de risco em código fonte.
const
// Mude aqui a qtde maxima de trades por dia
cQtdeMaxOperacoesNoDia = 5;
var
iQtdeOperacoesNoDia: integer;
iDataAtual: integer;
bJaContouOperacao: boolean;
fMedia: float;
begin
// Inicialização do contador de ordens do dia
if Date <> iDataAtual then
begin
iDataAtual := Date;
iQtdeOperacoesNoDia := 0;
bJaContouOperacao := false;
end;
// Setup de cruzamento de Media movel só para gerar operações
fMedia := Media(3,Close);
// Realiza abertura de posições apenas se número maximo de operação
// não tiver sido atingido
if iQtdeOperacoesNoDia < cQtdeMaxOperacoesNoDia then
begin
// COMPRA se fechamento cruzar media para cima e
// VENDE se fechamento cruzar media pra baixo
if (Close > fMedia) and (Close[1] <= fMedia[1]) and Not HasPosition then BuyAtMarket;
if (Close < fMedia) and (Close[1] >= fMedia[1]) and Not HasPosition then SellShortAtMarket;
end;
// Contabiliza a abertura da posição como mais uma operação no dia
if (isBought or isSold) and Not bJaContouOperacao then
begin
iQtdeOperacoesNoDia := iQtdeOperacoesNoDia + 1;
bJaContouOperacao := true;
end;
// Posiciona ordens para gestão do trade
if isBought then
begin
SellShortStop(buyPrice - 5*MinPriceIncrement);
SellShortLimit(buyPrice + 15*MinPriceIncrement);
end;
// Posiciona ordens para gestão do trade
if isSold then
begin
BuyStop(sellPrice + 5*MinPriceIncrement);
BuyLimit(sellPrice - 15*MinPriceIncrement);
end;
// Encerra posicao no mesmo dia
if (Time >= 1645) and hasPosition then ClosePosition;
// Se posição for encerrada ativa novamente o contador
if Not IsBought and Not isSold and bJaContouOperacao then bJaContouOperacao := false;
// Apenas para inspeção gráfica do sinal
Plot(fMedia);
end
Como limitar trades por objetivo de ganho ou limite de perda
O código abaixo apresenta a funcionalidade em código fonte para limitar a realização de trades baseado no resultado do dia.
Caso o resultado das operações da estratégia atinja o objetivo de ganho ou o limite de perda, fornecidos em valores absolutos e unidade financeira pelos parâmetros pLimitePerdaDiaria e pObjetivoGanhoDiario, a estratégia não realiza mais operações e encerra posições abertas.
O parâmetro pPlotarResultado pode receber os valores “FECHADO”, “ABERTO” e “TOTAL”, para se referir ao resultado de trades fechados, resultado do trade em aberto e resultado total do dia (FECHADO + ABERTO), respectivamente.
input
pPlotarResultado("ABERTO");
pLimitePerdaDiaria(200.00);
pObjetivoGanhoDiario(600.00);
var
fResultado: float;
fResultadoDiario: float;
iDataTeste: integer;
iHora: integer;
begin
//-----------------------------------------------------------
//Plots podem ser excluídos...servem apenas para demonstração
// Resultado fechado do dia
If pPlotarResultado = "FECHADO" then
begin
fResultado := DailyResult(false);
plot(fResultado);
SetPlotStyle(1,psSolid);
SetPlotColor(1,clWhite);
end;
// Resultado até o momento no dia (fechado + aberto)
If pPlotarResultado = "TOTAL" then
begin
fResultado := DailyResult(true);
plot2(fResultado);
SetPlotStyle(2,psDash);
SetPlotColor(2,clRed);
end;
// Resultado do trade aberto
If pPlotarResultado = "ABERTO" then
begin
fResultado := DailyResult(true) - DailyResult(false);
if fResultado <> 0 then
plot3(fResultado);
SetPlotStyle(3,psDash);
if fResultado >= 0 then SetPlotColor(3,clGreen)
else SetPlotColor(3,clRed);
SetPlotType(3, igHistogram);
end;
//-----------------------------------------------------------
// Estratégias apenas opera se resultado do dia não
// tiver atingido objetivo de ganho ou limite de perda
iDataTeste := ELDate(2023,2,10);
fResultadoDiario := DailyResult(true);
if (fResultadoDiario > -1*pLimitePerdaDiaria)
and (fResultadoDiario < pObjetivoGanhoDiario) then
begin
// SIMULAÇÃO DE ORDENS PARA FINS DE EXEMPLO
for iHora := 0 to 8 do
begin
if (Date = iDataTeste) and (Time = (0900 + iHora*100)) then
if random(2) = 0 then BuyAtMarket else SellShortAtMarket;
if (Date = iDataTeste) and (Time = (0930 + iHora*100)) then
ClosePosition;
end;
end
//Se resultado excedeu objetivo de ganho ou limite de perda
//e houver posição aberta, então encerra a posição.
else if hasPosition then ClosePosition;
end;
Limite de horário para encerramento de posição
O código abaixo apresenta a funcionalidade em código fonte para encerramento de posição a partir de um determinado horário. É um exemplo útil para quem opera daytrade e não deseja/não pode correr o risco de carregar operação para o dia seguinte.
var
bBarraDesejada : boolean;
pDataDesejada,pHorarioDesejado : integer;
//Util apenas para Backtesting em Gráfico de Renko
pMargemMinutos: integer;
begin
pHorarioDesejado := 1645;
pMargemMinutos := 15;
//Para Gráficos de Candle/Renko executados em tempo real
//if Time > pHorarioDesejado then
//Para Gráficos de Renko, em backtesting, utiliza-se uma margem de tempo em torno do horário desejado
if (Time >= CalcTIme(pHorarioDesejado, -pMargemMinutos)) then
begin
bBarraDesejada := true;
//Encerra posição caso esteja comprado/vendido
if isBought or isSold then ClosePosition;
end
else
bBarraDesejada := false;
end;
Stoploss simples (fixo)
O código abaixo apresenta um exemplo de stoploss fixo e take profit (alvo de lucro da operação), para uma relação de risco/ganho de 3:1 em função de quantidade de ticks, aplicado a uma estratégia de posicionamento. O código tem um limite de horário para abertura e fechamento de posição, o qual pode ser alterado pelos parâmetros.
OBS 1: A versão é compatível com o Editor de Estratégias e Módulo de Automação de Estratégias. Devido a um bug do Profit, é necessário ter um comando ClosePosition, pois do contrário a ferramenta informa equivocadamente que não existem ordens para encerrar posição.
const
//Relação risco/ganho de 3:1
cStopEmTicks = 10;
cAlvoEmTicks = 30;
cStopOffsetEmTicks = 50;
input
bGestaoDeRiscoPelaEstrategia(true);
iHorarioInicioAberturaPosicao(0905);
iHorarioFimAberturaPosicao(1630);
iHorarioEncerramentoDaytrade(1645);
var
iCaraCoroa: integer;
bSinalCompra, bSinalVenda, bPosicionado: boolean;
fPrecoStop, fPrecoAlvo, fPrecoStopOffset: float;
bConfigurouRisco: boolean;
begin
bSinalCompra := false;
bSinalVenda := false;
bPosicionado := hasPosition;
//ESTRATÉGIA CARA OU COROA!
//Gera um numero aleatorio de 0 a 9. Se for menor igual a 4, gera
//sinal de compra, se for maior que 4 geral sinal de venda
if Not bPosicionado
and (Time >= iHorarioInicioAberturaPosicao)
and (Time <= iHorarioFimAberturaPosicao)
then
begin
//Número aleatório foi substituido por minuto par ou impar para permitir depurar
//melhor o robô quando a estratégia é inserida multiplas vezes: como indicador e como execução
//iCaraCoroa := Random(10);
iCaraCoroa := mod(Time,2);
if iCaraCoroa = 0 then bSinalCompra := true
else bSinalVenda := true;
end;
//Gera ordem de compra a mercado quando há um Sinal de COMPRA
//e define ordem stoploss e take profit
if bSinalCompra then BuyAtMarket;
//Gera ordem de venda a mercado quando há um Sinal de VENDA
//e define ordem stoploss e take profit
if bSinalVenda then SellShortAtMarket;
if bGestaoDeRiscoPelaEstrategia then
begin
//POSIÇÃO COMPRADA
//Código responsável pela manutenção das ordens de stoploss e take profit
if isBought then
begin
if not bConfigurouRisco then
begin
fPrecoStop := BuyPrice - cStopEmTicks*MinPriceIncrement;
fPrecoAlvo := BuyPrice + cAlvoEmTicks*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop - cStopOffsetEmTicks*MinPriceIncrement;
bConfigurouRisco := true;
end;
SellToCoverStop(fPrecoStop,fPrecoStopOffset);
SellToCoverLimit(fPrecoAlvo);
end;
//POSIÇÃO VENDIDA
//Código responsável pela manutenção das ordens de stoploss e take profit
if isSold then
begin
if not bConfigurouRisco then
begin
fPrecoStop := SellPrice + cStopEmTicks*MinPriceIncrement;
fPrecoAlvo := SellPrice - cAlvoEmTicks*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop + cStopOffsetEmTicks*MinPriceIncrement;
bConfigurouRisco := true;
end;
BuyToCoverStop(fPrecoStop,fPrecoStopOffset);
BuyToCoverLimit(fPrecoAlvo);
end;
//Encerra posicao
if (Time >= iHorarioEncerramentoDaytrade)
and HasPosition
then ClosePosition;
if Not HasPosition then bConfigurouRisco := false;
end;
// Plot de Stop e Alvo para inspeção visual do código
bPosicionado := hasPosition;
if bPosicionado or bPosicionado[1] or bPosicionado[2] then
begin
PlotN(1,fPrecoStop);
PlotN(2,fPrecoStopOffset);
PlotN(3,fPrecoAlvo);
SetPlotColor(1,clRed);
SetPlotColor(2,clRed);
SetPlotColor(3,clGreen);
SetPlotStyle(1,psDash);
SetPlotStyle(2,psDash);
SetPlotStyle(3,psDash);
SetPlotWidth(1,2);
SetPlotWidth(2,2);
SetPlotWidth(3,2);
end;
end;
Stoploss com Breakeven
O código abaixo apresenta um exemplo de Stoploss fixo + Breakeven (alvo de lucro da operação), para uma relação de risco/ganho de 3:1 em função de quantidade de ticks, aplicado a uma estratégia de posicionamento aleatório com uma operação por dia.
OBS 1: A versão é compatível com o Editor de Estratégias e Módulo de Automação de Estratégias. Devido a um bug do Profit, é necessário ter um comando ClosePosition, pois do contrário a ferramenta informa equivocadamente que não existem ordens para encerrar posição.
const
//Relação risco/ganho de 3:1
cStopEmTicks = 30;
cStopOffsetEmTicks = 20;
cBreakevenEmTicks = 30;
cAlvoEmTIcks = 90;
input
bGestaoDeRiscoPelaEstrategia(true);
iHorarioInicioAberturaPosicao(0905);
iHorarioFimAberturaPosicao(1630);
iHorarioEncerramentoDaytrade(1645);
var
iCaraCoroa: integer;
bSinalCompra, bSinalVenda, bPosicionado: boolean;
fPrecoStop, fPrecoAlvo, fPrecoStopOffset: float;
bConfigurouRiscoInicial: boolean;
begin
bSinalCompra := false;
bSinalVenda := false;
bPosicionado := hasPosition;
//ESTRATÉGIA CARA OU COROA!
//Gera um numero aleatorio de 0 a 9. Se for menor igual a 4, gera
//sinal de compra, se for maior que 4 geral sinal de venda
if Not bPosicionado
and (Time >= iHorarioInicioAberturaPosicao)
and (Time <= iHorarioFimAberturaPosicao)
then
begin
//Número aleatório foi substituido por minuto par ou impar para permitir depurar
//melhor o robô quando a estratégia é inserida multiplas vezes: como indicador e como execução
//iCaraCoroa := Random(10);
iCaraCoroa := mod(Time,2);
if iCaraCoroa = 0 then bSinalCompra := true
else bSinalVenda := true;
end;
//Gera ordem de compra a mercado quando há um Sinal de COMPRA
//e define ordem stoploss e take profit
if bSinalCompra then BuyAtMarket;
//Gera ordem de venda a mercado quando há um Sinal de VENDA
//e define ordem stoploss e take profit
if bSinalVenda then SellShortAtMarket;
if bGestaoDeRiscoPelaEstrategia then
begin
//Código responsável pela manutenção das ordens de stoploss e take profit
if isBought then
begin
if Not bConfigurouRiscoInicial then
begin
fPrecoStop := BuyPrice - cStopEmTicks*MinPriceIncrement;
fPrecoAlvo := BuyPrice + cAlvoEmTicks*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop - cStopOffsetEmTicks*MinPriceIncrement;
bConfigurouRiscoInicial := true;
end;
if Close >= (BuyPrice + cBreakevenEmTicks*MinPriceIncrement) then
begin
fPrecoStop := BuyPrice;
fPrecoStopOffset := fPrecoStop-cStopOffsetEmTicks*MinPriceIncrement;
end;
SellToCoverStop(fPrecoStop,fPrecoStopOffset);
SellToCoverLimit(fPrecoAlvo);
end;
//Código responsável pela manutenção das ordens de stoploss e take profit
if isSold then
begin
if Not bConfigurouRiscoInicial then
begin
fPrecoStop := SellPrice + cStopEmTicks*MinPriceIncrement;
fPrecoAlvo := SellPrice - cAlvoEmTicks*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop + cStopOffsetEmTicks*MinPriceIncrement;
bConfigurouRiscoInicial := true;
end;
if Close <= (SellPrice - cBreakevenEmTicks*MinPriceIncrement) then
begin
fPrecoStop := SellPrice;
fPrecoStopOffset := fPrecoStop+cStopOffsetEmTicks*MinPriceIncrement;
end;
BuyToCoverStop(fPrecoStop,fPrecoStopOffset);
BuyToCoverLimit(fPrecoAlvo);
end;
//Encerra posicao
if (Time >= iHorarioEncerramentoDaytrade)
and HasPosition
then ClosePosition;
if Not hasPosition and bConfigurouRiscoInicial then bConfigurouRiscoInicial := false;
end;
bPosicionado := hasPosition;
// Plot de Stop e Alvo para inspeção visual do código
if bPosicionado or bPosicionado[1] or bPosicionado[2] then
begin
PlotN(1,fPrecoStop);
PlotN(2,fPrecoStopOffset);
PlotN(3,fPrecoAlvo);
SetPlotColor(1,clRed);
SetPlotColor(2,clRed);
SetPlotColor(3,clGreen);
SetPlotStyle(1,psDash);
SetPlotStyle(2,psDash);
SetPlotStyle(3,psDash);
SetPlotWidth(1,2);
SetPlotWidth(2,2);
SetPlotWidth(3,2);
end;
end;
Stoploss móvel (Versão contínua)
O código abaixo apresenta um exemplo de stoploss móvel (Versão contínua), ou seja, valor de stop é atualizado a cada fechamento de candle. Só não é atualizado a cada tick por uma limitação do Profit.
O stop será alterado para cOffsetStopEmTicks em relação ao preço de fechamento do candle, não podendo o valor do stop retroceder. O código pode ser alterado para calcular o stop móvel em relação ao valor máximo do candle.
O exemplo também conta com ordem take profit (alvo de lucro da operação) para uma relação de risco/ganho de 3:1 em função de quantidade de ticks, aplicado a uma estratégia de posicionamento aleatório com uma operação por dia.
OBS 1: A versão é compatível com o Editor de Estratégias e Módulo de Automação de Estratégias. Devido a um bug do Profit, é necessário ter um comando ClosePosition, pois do contrário a ferramenta informa equivocadamente que não existem ordens para encerrar posição.
const
//Relação risco/ganho de 3:1
cStopEmTicks = 15;
cAlvoEmTicks = 45;
cTraillingStopTrigger = 20;
cTrailingStopOffset = 10;
cStopOffsetEmTicks = 50;
input
bGestaoDeRiscoPelaEstrategia(true);
iHorarioInicioAberturaPosicao(0905);
iHorarioFimAberturaPosicao(1630);
iHorarioEncerramentoDaytrade(1645);
var
iCaraCoroa: integer;
bSinalCompra, bSinalVenda, bPosicionado: boolean;
fPrecoStop, fPrecoAlvo, fPrecoStopOffset: float;
bConfigurouRiscoInicial: boolean;
bTrailingStopAtivado: boolean;
begin
bSinalCompra := false;
bSinalVenda := false;
bPosicionado := hasPosition;
//ESTRATÉGIA CARA OU COROA!
//Gera um numero aleatorio de 0 a 9. Se for menor igual a 4, gera
//sinal de compra, se for maior que 4 geral sinal de venda
if Not bPosicionado
and (Time >= iHorarioInicioAberturaPosicao)
and (Time <= iHorarioFimAberturaPosicao)
then
begin
//Número aleatório foi substituido por minuto par ou impar para permitir depurar
//melhor o robô quando a estratégia é inserida multiplas vezes: como indicador e como execução
//iCaraCoroa := Random(10);
iCaraCoroa := mod(Time,2);
if iCaraCoroa = 0 then bSinalCompra := true
else bSinalVenda := true;
end;
//Gera ordem de compra a mercado quando há um Sinal de COMPRA
//e define ordem stoploss e take profit
if bSinalCompra then BuyAtMarket;
//Gera ordem de venda a mercado quando há um Sinal de VENDA
//e define ordem stoploss e take profit
if bSinalVenda then SellShortAtMarket;
if bGestaoDeRiscoPelaEstrategia then
begin
//POSIÇÃO COMPRADA
//Código responsável pela manutenção das ordens de stoploss e take profit
if isBought then
begin
if Not bConfigurouRiscoInicial then
begin
fPrecoStop := BuyPrice - cStopEmTicks*MinPriceIncrement;
fPrecoAlvo := BuyPrice + cAlvoEmTicks*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop - cStopOffsetEmTicks*MinPriceIncrement;
bConfigurouRiscoInicial := true;
end;
if ((Close >= (BuyPrice + cTraillingStopTrigger*MinPriceIncrement))
or (cTraillingStopTrigger = 0))
and (not bTrailingStopAtivado) then bTrailingStopAtivado := true;
if ((Close - cTrailingStopOffset*MinPriceIncrement) >= fPrecoStop)
and (bTrailingStopAtivado) then
begin
fPrecoStop := Close - cTrailingStopOffset*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop - cStopOffsetEmTicks*MinPriceIncrement;
end;
SellToCoverStop(fPrecoStop,fPrecoStopOffset);
SellToCoverLimit(fPrecoAlvo);
end;
//POSIÇÃO VENDIDA
//Código responsável pela manutenção das ordens de stoploss e take profit
if isSold then
begin
if Not bConfigurouRiscoInicial then
begin
fPrecoStop := SellPrice + cStopEmTicks*MinPriceIncrement;
fPrecoAlvo := SellPrice - cAlvoEmTicks*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop + cStopOffsetEmTicks*MinPriceIncrement;
bConfigurouRiscoInicial := true;
end;
if ((Close <= (SellPrice - cTraillingStopTrigger*MinPriceIncrement))
or (cTraillingStopTrigger = 0))
and (not bTrailingStopAtivado) then bTrailingStopAtivado := true;
if ((Close + cTrailingStopOffset*MinPriceIncrement) <= fPrecoStop)
and (bTrailingStopAtivado) then
begin
fPrecoStop := Close + cTrailingStopOffset*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop + cStopOffsetEmTicks*MinPriceIncrement;
end;
BuyToCoverStop(fPrecoStop,fPrecoStopOffset);
BuyToCoverLimit(fPrecoAlvo);
end;
//Encerra posicao comprada no horario limite
if (Time >= iHorarioEncerramentoDaytrade)
and HasPosition
then ClosePosition;
if Not hasPosition and bConfigurouRiscoInicial then
begin
bConfigurouRiscoInicial := false;
bTrailingStopAtivado := false;
end;
end;
// Plot de Stop e Alvo para inspeção visual do código
bPosicionado := hasPosition;
if bPosicionado or bPosicionado[1] or bPosicionado[2] then
begin
PlotN(1,fPrecoStop);
PlotN(2,fPrecoStopOffset);
PlotN(3,fPrecoAlvo);
SetPlotColor(1,clRed);
SetPlotColor(2,clRed);
SetPlotColor(3,clGreen);
SetPlotStyle(1,psDash);
SetPlotStyle(2,psDash);
SetPlotStyle(3,psDash);
SetPlotWidth(1,2);
SetPlotWidth(2,2);
SetPlotWidth(3,2);
end;
end;
Stoploss móvel (Versão baseada em passos)
O código abaixo apresenta um exemplo de stoploss móvel (Versão discreta, baseada em passos), ou seja, valor de stop é atualizado cada vez que o preço de fechamento do candle supera o passo definido em cTrailingStepEmTicks. Só não é atualizado a cada tick por uma limitação do Profit.
O stop será alterado para cOffsetStop em relação ao preço do último passo alcançado, não podendo o valor do stop retroceder. O código pode ser alterado para calcular o stop móvel em relação ao valor máximo do candle.
O exemplo também conta com ordem take profit (alvo de lucro da operação) em posições compradas, para uma relação de risco/ganho de 3:1. O raciocínio para posições vendidas é análogo.
OBS 1: A versão é compatível com o Editor de Estratégias e Módulo de Automação de Estratégias. Devido a um bug do Profit, é necessário ter um comando ClosePosition, pois do contrário a ferramenta informa equivocadamente que não existem ordens para encerrar posição.
const
//Relação risco/ganho de 3:1
cStopEmTicks = 15;
cAlvoEmTicks = 45;
cTraillingStopTrigger = 0;
cTrailingStopOffset = 8;
cTrailingStepEmTicks = 10;
cStopOffsetEmTicks = 10;
input
bGestaoDeRiscoPelaEstrategia(true);
iHorarioInicioAberturaPosicao(1000);
iHorarioFimAberturaPosicao(1630);
iHorarioEncerramentoDaytrade(1645);
var
iCaraCoroa: integer;
bSinalCompra, bSinalVenda, bPosicionado: boolean;
fPrecoStop, fPrecoAlvo, fPrecoStopOffset: float;
fFloorTraillingStop : float;
bConfigurouRiscoInicial: boolean;
bTrailingStopAtivado: boolean;
begin
bSinalCompra := false;
bSinalVenda := false;
bPosicionado := hasPosition;
//ESTRATÉGIA CARA OU COROA!
//Gera um numero aleatorio de 0 a 9. Se for menor igual a 4, gera
//sinal de compra, se for maior que 4 geral sinal de venda
if Not bPosicionado
and (Time >= iHorarioInicioAberturaPosicao)
and (Time <= iHorarioFimAberturaPosicao)
then
begin
//Número aleatório foi substituido por minuto par ou impar para permitir depurar
//melhor o robô quando a estratégia é inserida multiplas vezes: como indicador e como execução
//iCaraCoroa := Random(10);
iCaraCoroa := mod(Time,2);
if iCaraCoroa = 0 then bSinalCompra := true
else bSinalVenda := true;
end;
//Gera ordem de compra a mercado quando há um Sinal de COMPRA
//e define ordem stoploss e take profit
if bSinalCompra then BuyAtMarket;
//Gera ordem de venda a mercado quando há um Sinal de VENDA
//e define ordem stoploss e take profit
if bSinalVenda then SellShortAtMarket;
if bGestaoDeRiscoPelaEstrategia then
begin
//POSIÇÃO COMPRADA
//Código responsável pela manutenção das ordens de stoploss e take profit
if isBought then
begin
if Not bConfigurouRiscoInicial then
begin
fPrecoStop := BuyPrice - cStopEmTicks*MinPriceIncrement;
fPrecoAlvo := BuyPrice + cAlvoEmTicks*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop - cStopOffsetEmTicks*MinPriceIncrement;
bConfigurouRiscoInicial := true;
end;
if ((Close >= (BuyPrice + cTraillingStopTrigger*MinPriceIncrement))
or (cTraillingStopTrigger = 0))
and (not bTrailingStopAtivado) then bTrailingStopAtivado := true;
fFloorTraillingStop := BuyPrice
+ floor((Close - BuyPrice)/(cTrailingStepEmTicks*MinPriceIncrement))
*cTrailingStepEmTicks*MinPriceIncrement;
if ((fFloorTraillingStop-cTrailingStopOffset*MinPriceIncrement) >= fPrecoStop)
and bTrailingStopAtivado then
fPrecoStop := fFloorTraillingStop - cTrailingStopOffset*MinPriceIncrement;
SellToCoverStop(fPrecoStop,fPrecoStopOffset);
SellToCoverLimit(fPrecoAlvo);
end;
//POSIÇÃO VENDIDA
//Código responsável pela manutenção das ordens de stoploss e take profit
if isSold Then
begin
if Not bConfigurouRiscoInicial then
begin
fPrecoStop := SellPrice + cStopEmTicks*MinPriceIncrement;
fPrecoAlvo := SellPrice - cAlvoEmTicks*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop + cStopOffsetEmTicks*MinPriceIncrement;
bConfigurouRiscoInicial := true;
end;
if ((Close <= (SellPrice - cTraillingStopTrigger*MinPriceIncrement))
or (cTraillingStopTrigger = 0))
and (not bTrailingStopAtivado) then bTrailingStopAtivado := true;
if Close <= SellPrice then
fFloorTraillingStop := SellPrice
- floor((SellPrice - Close)/(cTrailingStepEmTicks*MinPriceIncrement))
*cTrailingStepEmTicks*MinPriceIncrement;
if ((fFloorTraillingStop+cTrailingStopOffset*MinPriceIncrement) <= fPrecoStop)
and bTrailingStopAtivado then
fPrecoStop := fFloorTraillingStop + cTrailingStopOffset*MinPriceIncrement;
BuyToCoverStop(fPrecoStop,fPrecoStopOffset);
BuyToCoverLimit(fPrecoAlvo);
end;
//Encerra posicao
if (Time >= iHorarioEncerramentoDaytrade)
and HasPosition
then ClosePosition;
if Not hasPosition and bConfigurouRiscoInicial then
begin
bConfigurouRiscoInicial := false;
bTrailingStopAtivado := false;
end;
end;
// Plot de Stop e Alvo para inspeção visual do código
bPosicionado := hasPosition;
if bPosicionado or bPosicionado[1] or bPosicionado[2] then
begin
PlotN(1,fPrecoStop);
PlotN(2,fPrecoStopOffset);
PlotN(3,fPrecoAlvo);
SetPlotColor(1,clRed);
SetPlotColor(2,clRed);
SetPlotColor(3,clGreen);
SetPlotStyle(1,psDash);
SetPlotStyle(2,psDash);
SetPlotStyle(3,psDash);
SetPlotWidth(1,2);
SetPlotWidth(2,2);
SetPlotWidth(3,2);
end;
end;
Stoploss móvel (Versão contínua) + Breakeven
O código abaixo apresenta um exemplo avançado de stoploss móvel com Breakeven na versão contínua, ou seja, valor de stop é atualizado para cada valor de fechamento de candle encerrado. Só não é atualizado a cada tick por uma limitação do Profit.
O stop será alterado para cOffsetStop em relação ao maior preço de fechamento alcançado desde a abertura da posição. O código pode ser alterado para calcular o stop móvel em relação ao valor máximo do candle.
O exemplo também conta com ordem take profit (alvo de lucro da operação) em posições compradas, para uma relação de risco/ganho de 3:1. O raciocínio para posições vendidas é análogo.
OBS 1: A versão é compatível com o Editor de Estratégias e Módulo de Automação de Estratégias. Devido a um bug do Profit, é necessário ter um comando ClosePosition, pois do contrário a ferramenta informa equivocadamente que não existem ordens para encerrar posição.
const
//Relação risco/ganho de 3:1
cStopEmTicks = 30;
cStopOffsetEmTicks = 10;
cTrailingStopOffset = 15;
cBreakevenEmTicks = 10;
cTraillingStopTrigger = 20;
cAlvoEmTicks = 90;
input
bGestaoDeRiscoPelaEstrategia(true);
iHorarioInicioAberturaPosicao(0905);
iHorarioFimAberturaPosicao(1630);
iHorarioEncerramentoDaytrade(1645);
var
iCaraCoroa: integer;
bSinalCompra, bSinalVenda, bPosicionado: boolean;
fPrecoStop, fPrecoAlvo, fPrecoStopOffset: float;
bBreakevenAtivado: boolean;
bConfigurouRiscoInicial: boolean;
bTrailingStopAtivado: boolean;
begin
bSinalCompra := false;
bSinalVenda := false;
bPosicionado := hasPosition;
//ESTRATÉGIA CARA OU COROA!
//Gera um numero aleatorio de 0 a 9. Se for menor igual a 4, gera
//sinal de compra, se for maior que 4 geral sinal de venda
if Not bPosicionado
and (Time >= iHorarioInicioAberturaPosicao)
and (Time <= iHorarioFimAberturaPosicao)
then
begin
//Número aleatório foi substituido por minuto par ou impar para permitir depurar
//melhor o robô quando a estratégia é inserida multiplas vezes: como indicador e como execução
//iCaraCoroa := Random(10);
iCaraCoroa := mod(Time,2);
if iCaraCoroa = 0 then bSinalCompra := true
else bSinalVenda := true;
end;
//Gera ordem de compra a mercado quando há um Sinal de COMPRA
//e define ordem stoploss e take profit
if bSinalCompra then BuyAtMarket;
//Gera ordem de venda a mercado quando há um Sinal de VENDA
//e define ordem stoploss e take profit
if bSinalVenda then SellShortAtMarket;
if bGestaoDeRiscoPelaEstrategia then
begin
//Código responsável pela manutenção das ordens de stoploss e take profit
if isBought then
begin
if Not bConfigurouRiscoInicial then
begin
fPrecoStop := BuyPrice - cStopEmTicks*MinPriceIncrement;
fPrecoAlvo := BuyPrice + cAlvoEmTicks*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop - cStopOffsetEmTicks*MinPriceIncrement;
bConfigurouRiscoInicial := true;
end;
if ((Close >= (BuyPrice + cTraillingStopTrigger*MinPriceIncrement))
or (cTraillingStopTrigger = 0))
and (not bTrailingStopAtivado) then bTrailingStopAtivado := true;
if ((Close - cTrailingStopOffset*MinPriceIncrement) >= fPrecoStop)
and bTrailingStopAtivado then
fPrecoStop := Close - cTrailingStopOffset*MinPriceIncrement;
if (Close >= (BuyPrice + cBreakevenEmTicks*MinPriceIncrement))
and (not bBreakevenAtivado) then
begin
bBreakevenAtivado := true;
if fPrecoStop < BuyPrice then fPrecoStop := BuyPrice;
end;
fPrecoStopOffset := fPrecoStop-cStopOffsetEmTicks*MinPriceIncrement;
SellToCoverStop(fPrecoStop,fPrecoStopOffset);
SellToCoverLimit(fPrecoAlvo);
end;
//Código responsável pela manutenção das ordens de stoploss e take profit
if isSold then
begin
if Not bConfigurouRiscoInicial then
begin
fPrecoStop := SellPrice + cStopEmTicks*MinPriceIncrement;
fPrecoAlvo := SellPrice - cAlvoEmTicks*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop + cStopOffsetEmTicks*MinPriceIncrement;
bConfigurouRiscoInicial := true;
end;
if ((Close <= (SellPrice - cTraillingStopTrigger*MinPriceIncrement))
or (cTraillingStopTrigger = 0))
and (not bTrailingStopAtivado) then bTrailingStopAtivado := true;
if ((Close + cTrailingStopOffset*MinPriceIncrement) <= fPrecoStop)
and bTrailingStopAtivado then
fPrecoStop := Close + cTrailingStopOffset*MinPriceIncrement;
if (Close <= (SellPrice - cBreakevenEmTicks*MinPriceIncrement))
and (not bBreakevenAtivado) then
begin
bBreakevenAtivado := true;
if fPrecoStop > SellPrice then fPrecoStop := SellPrice;
end;
fPrecoStopOffset := fPrecoStop + cStopOffsetEmTicks*MinPriceIncrement;
BuyToCoverStop(fPrecoStop,fPrecoStopOffset);
BuyToCoverLimit(fPrecoAlvo);
end;
//Encerra posicao
if (Time >= iHorarioEncerramentoDaytrade)
and HasPosition
then ClosePosition;
if Not hasPosition and bConfigurouRiscoInicial then
begin
bConfigurouRiscoInicial := false;
bBreakevenAtivado := false;
bTrailingStopAtivado := false;
end;
end;
// Plot de Stop e Alvo para inspeção visual do código
bPosicionado := hasPosition;
if bPosicionado or bPosicionado[1] or bPosicionado[2] then
begin
PlotN(1,fPrecoStop);
PlotN(2,fPrecoStopOffset);
PlotN(3,fPrecoAlvo);
SetPlotColor(1,clRed);
SetPlotColor(2,clRed);
SetPlotColor(3,clGreen);
SetPlotStyle(1,psDash);
SetPlotStyle(2,psDash);
SetPlotStyle(3,psDash);
SetPlotWidth(1,2);
SetPlotWidth(2,2);
SetPlotWidth(3,2);
end
else
begin
NoPlot(1);
NoPlot(2);
NoPlot(3);
end;
end;
Stoploss móvel (Versão baseada em passos) + Breakeven
O código abaixo apresenta um exemplo avançado de stoploss móvel com Breakeven na versão discreta (baseada em passos), ou seja, valor de stop é atualizado para cada valor de fechamento que supera o passo definido (cTrailingStepEmTicks). Só não é atualizado a cada tick por uma limitação do Profit.
O stop será alterado para cOffsetStop em relação ao último passo alcançado pelo maior preço de fechamento de candle desde a abertura da posição. O código pode ser alterado para calcular o stop móvel em relação ao valor máximo do candle.
O exemplo também conta com ordem take profit (alvo de lucro da operação) em posições compradas, para uma relação de risco/ganho de 3:1. O raciocínio para posições vendidas é análogo.
OBS 1: A versão é compatível com o Editor de Estratégias e Módulo de Automação de Estratégias. Devido a um bug do Profit, é necessário ter um comando ClosePosition, pois do contrário a ferramenta informa equivocadamente que não existem ordens para encerrar posição.
const
//Relação risco/ganho de 3:1
cStopEmTicks = 30;
cBreakevenEmTicks = 10;
cTraillingStopTrigger = 20;
cTrailingStepEmTicks = 20;
cTrailingStopOffset = 10;
cStopOffsetEmTicks = 10;
cAlvoEmTIcks = 90;
input
bGestaoDeRiscoPelaEstrategia(true);
iHorarioInicioAberturaPosicao(0905);
iHorarioFimAberturaPosicao(1630);
iHorarioEncerramentoDaytrade(1645);
var
iCaraCoroa: integer;
bSinalCompra, bSinalVenda, bPosicionado: boolean;
fPrecoStop, fPrecoAlvo, fPrecoStopOffset: float;
fFloorTraillingStop: float;
bBreakevenAtivado: boolean;
bConfigurouRiscoInicial: boolean;
bTrailingStopAtivado: boolean;
begin
bSinalCompra := false;
bSinalVenda := false;
bPosicionado := hasPosition;
//ESTRATÉGIA CARA OU COROA!
//Gera um numero aleatorio de 0 a 9. Se for menor igual a 4, gera
//sinal de compra, se for maior que 4 geral sinal de venda
if Not bPosicionado
and (Time >= iHorarioInicioAberturaPosicao)
and (Time <= iHorarioFimAberturaPosicao)
then
begin
//Número aleatório foi substituido por minuto par ou impar para permitir depurar
//melhor o robô quando a estratégia é inserida multiplas vezes: como indicador e como execução
//iCaraCoroa := Random(10);
iCaraCoroa := mod(Time,2);
if iCaraCoroa = 0 then bSinalCompra := true
else bSinalVenda := true;
end;
//Gera ordem de compra a mercado quando há um Sinal de COMPRA
//e define ordem stoploss e take profit
if bSinalCompra then BuyAtMarket;
//Gera ordem de venda a mercado quando há um Sinal de VENDA
//e define ordem stoploss e take profit
if bSinalVenda then SellShortAtMarket;
if bGestaoDeRiscoPelaEstrategia then
begin
//Código responsável pela manutenção das ordens de stoploss e take profit
if isBought then
begin
if Not bConfigurouRiscoInicial then
begin
fPrecoStop := BuyPrice - cStopEmTicks*MinPriceIncrement;
fPrecoAlvo := BuyPrice + cAlvoEmTicks*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop - cStopOffsetEmTicks*MinPriceIncrement;
bConfigurouRiscoInicial := true;
end;
if ((Close >= (BuyPrice + cTraillingStopTrigger*MinPriceIncrement))
or (cTraillingStopTrigger = 0))
and (not bTrailingStopAtivado) then bTrailingStopAtivado := true;
fFloorTraillingStop := BuyPrice
+ floor((Close - BuyPrice)/(cTrailingStepEmTicks*MinPriceIncrement))
*cTrailingStepEmTicks*MinPriceIncrement;
if ((fFloorTraillingStop-cTrailingStopOffset*MinPriceIncrement) >= fPrecoStop)
and (Close >= BuyPrice+cTrailingStepEmTicks*MinPriceIncrement)
and bTrailingStopAtivado then
fPrecoStop := fFloorTraillingStop - cTrailingStopOffset*MinPriceIncrement;
if (Close >= (BuyPrice + cBreakevenEmTicks*MinPriceIncrement))
and (not bBreakevenAtivado) then
begin
bBreakevenAtivado := true;
if fPrecoStop < BuyPrice then fPrecoStop := BuyPrice;
end;
fPrecoStopOffset := fPrecoStop-cStopOffsetEmTicks*MinPriceIncrement;
SellToCoverStop(fPrecoStop,fPrecoStopOffset);
SellToCoverLimit(fPrecoAlvo);
end;
//Código responsável pela manutenção das ordens de stoploss e take profit
if isSold then
begin
if Not bConfigurouRiscoInicial then
begin
fPrecoStop := SellPrice + cStopEmTicks*MinPriceIncrement;
fPrecoAlvo := SellPrice - cAlvoEmTicks*MinPriceIncrement;
fPrecoStopOffset := fPrecoStop + cStopOffsetEmTicks*MinPriceIncrement;
bConfigurouRiscoInicial := true;
end;
if ((Close <= (SellPrice - cTraillingStopTrigger*MinPriceIncrement))
or (cTraillingStopTrigger = 0))
and (not bTrailingStopAtivado) then bTrailingStopAtivado := true;
if Close <= SellPrice then
fFloorTraillingStop := SellPrice
- floor((SellPrice - Close)/(cTrailingStepEmTicks*MinPriceIncrement))
*cTrailingStepEmTicks*MinPriceIncrement;
if ((fFloorTraillingStop+cTrailingStopOffset*MinPriceIncrement) <= fPrecoStop)
and (Close <= SellPrice - cTrailingStepEmTicks*MinPriceIncrement)
and bTrailingStopAtivado then
fPrecoStop := fFloorTraillingStop + cTrailingStopOffset*MinPriceIncrement;
if (Close <= (SellPrice - cBreakevenEmTicks*MinPriceIncrement))
and (not bBreakevenAtivado) then
begin
bBreakevenAtivado := true;
if fPrecoStop > SellPrice then fPrecoStop := SellPrice;
end;
fPrecoStopOffset := fPrecoStop + cStopOffsetEmTicks*MinPriceIncrement;
BuyToCoverStop(fPrecoStop,fPrecoStopOffset);
BuyToCoverLimit(fPrecoAlvo);
end;
//Encerra posicao
if (Time >= iHorarioEncerramentoDaytrade)
and HasPosition
then ClosePosition;
if Not hasPosition and bConfigurouRiscoInicial then
begin
bConfigurouRiscoInicial := false;
bBreakevenAtivado := false;
bTrailingStopAtivado := false;
end;
end;
// Plot de Stop e Alvo para inspeção visual do código
bPosicionado := hasPosition;
if bPosicionado or bPosicionado[1] or bPosicionado[2] then
begin
PlotN(1,fPrecoStop);
PlotN(2,fPrecoStopOffset);
PlotN(3,fPrecoAlvo);
SetPlotColor(1,clRed);
SetPlotColor(2,clRed);
SetPlotColor(3,clGreen);
SetPlotStyle(1,psDash);
SetPlotStyle(2,psDash);
SetPlotStyle(3,psDash);
SetPlotWidth(1,2);
SetPlotWidth(2,2);
SetPlotWidth(3,2);
end
else
begin
NoPlot(1);
NoPlot(2);
NoPlot(3);
end;
end;
Confirmação de ordens por múltiplos sinais
O código abaixo apresenta um exemplo para o conceito de confirmação de compra por meio de dois sinais distintos: um sinal baseado em IFR e outro baseado em cruzamento de média.
Os sinais podem ser adaptados para quaisquer condições que se deseje. O importante deste exemplo é entender a lógica por trás de duplas confirmações ou múltiplas confirmações com janela de timeout para abertura de posição.
OBS 1: Como o foco do snippet é a confirmação de ordens com múltiplos sinais, a gestão de risco foi implementada da forma mais simples possível apenas para tornar o código funcional. Percebe-se que há um stop e alvo fixos na relação 3:1, onde o stop está 30 ticks atrás do preço de compra e o alvo a 90 ticks acima do preço de compra.
OBS 2: A parametrização dos indicadores, bem como a seleção dos indicadores deste exemplo não representam nenhuma recomendação de setup, sendo apenas um exemplo didático.
const
// Determina a qtde de candles a se aguardar a confirmação
// de sinal de compra
iTimeoutConfirmacao = 12;
// Limite para considerar sobrevenda no IFR
iLimiteSobreVendaIFR = 35;
input
iQtdePeriodosMedia(16);
iQtdePeriodosIFR(16);
//Compatibilidade com Módulo de Automação de Estratégias
bModuloAutomacao(false);
var
bSinalCompraIFR, bSinalCompraCruzMedia: boolean;
fIFR, fMedia: float;
iInteradorTimeout: integer;
bSinalCompraConfirmada: boolean;
bSinalCompraIFRativou, bSinalCompraCruzMediaAtivou: boolean;
bComprado: boolean;
bConfigurouRiscoOperacao: boolean;
fPrecoAlvo, fPrecoStop, fStopOffset: float;
begin
// Indicadores técnicos utilizados para sinais
bComprado := isBought;
fIFR := RSI(iQtdePeriodosIFR,0);
fMedia := Media(iQtdePeriodosMedia,Close);
bSinalCompraConfirmada := false;
//Sinais de compra individuais para indicadores
bSinalCompraCruzMedia := (Close > fMedia) and (Close[1] <= fMedia[1]);
bSinalCompraIFR := (fIFR > iLimiteSobreVendaIFR) and (fIFR[1] <= iLimiteSobreVendaIFR);
// Auxilio visual de sinais individuais
if bSinalCompraCruzMedia and Not bComprado then PlotText("S1", clBlue,-1,9);
if bSinalCompraIFR and Not bComprado then PlotText("S2", clYellow,0,9);
// Lógica para multiplas confirmações
// Se Timeout for zero a dupla confirmação de compra deve ocorrer
// no mesmo candle/box
if Not bComprado then
begin
if (iTimeoutConfirmacao = 0) and bSinalCompraCruzMedia and bSinalCompraIFR then
bSinalCompraConfirmada := true
else
if (iTimeoutConfirmacao > 0) then
begin
bSinalCompraConfirmada := false;
bSinalCompraIFRativou := false;
bSinalCompraCruzMediaAtivou := false;
for iInteradorTimeout := 0 to iTimeoutConfirmacao do
begin
if bSinalCompraCruzMedia[iInteradorTimeout] = true then bSinalCompraCruzMediaAtivou := true;
if bSinalCompraIFR[iInteradorTimeout] = true then bSinalCompraIFRativou := true;
if bSinalCompraCruzMediaAtivou and bSinalCompraIFRativou then bSinalCompraConfirmada := true;
end;
end;
end;
// Se houver multipla confirmação, executa ordem a mercado
if bSinalCompraConfirmada and Not bComprado then
begin
BuyAtMarket;
bConfigurouRiscoOperacao := false;
end;
bComprado := isBought;
// Configura risco da operação no Módulo de Automação (Ordem OCO)
// Para outras configurações de STOPLOSS, consulte os snippets no site
if bModuloAutomacao then
begin
if bComprado and Not bConfigurouRiscoOperacao then
begin
fPrecoAlvo := buyPrice + 450*MinPriceIncrement;
fPrecoStop := buyPrice - 150*MinPriceIncrement;
fStopOffset := fPrecoStop - 100*MinPriceIncrement;
SellShortStop(fPrecoStop, fStopOffset);
SellShortLimit(fPrecoAlvo);
end
else
//Proteção de pulo da ordem stop devido à gaps
if isBought and (Close < fStopOffset) then closePosition;
end
// Configura alvo e stoploss para Backtesting
else
begin
if bComprado then
begin
fPrecoAlvo := buyPrice + 450*MinPriceIncrement;
fPrecoStop := buyPrice - 150*MinPriceIncrement;
fStopOffset := fPrecoStop - 60*MinPriceIncrement;
SellToCoverStop(fPrecoStop, fStopOffset);
//Proteção de pulo da ordem stop devido à gaps
if isBought and (Close < fStopOffset) then closePosition;
if isBought then SellToCoverLimit(fPrecoAlvo);
end;
end;
end.
Gestão de Risco diária e Proteção de Ganhos
O código abaixo apresenta um exemplo de programação para fazer a gestão de risco do resultado diário de um robô.
Inicialmente, são estabelecidos para a estratégia o limite de perda (pLimitePerdaDiaria) e objetivo de ganho diário (pObjetivoGanhoDiario), bem como a proteção de ganho desejada (pProtecaoGanho), tudo em valor financeiro.
A medida que o robô faz as operações, caso o resultado atinja o limite de perda inicial, a estratégia para de operar durante o resto do dia.
Caso o objetivo de ganho seja atingido, a gestão de risco do código protege parte do ganho (pProtecaoGanho) e o robô continua a operar. Caso atinja novamente o objetivo de ganho, a partir do último patamar de ganho planejado, o lucro é novamente protegido.
input
pLimitePerdaDiaria(100.00);
pObjetivoGanhoDiario(300.00);
pProtecaoGanho(200.00);
pTempoReal(false);
var
fResultado: float;
fResultadoDiario: float;
iHora: integer;
fObjetivoAtualGanho, fLimiteAtualPerda: float;
fNovaReferencia: float;
bPrimeiraBarraDoDia : boolean;
iDataAtual : integer;
bPrimeiroTickDaBarra : boolean;
iBarraAtual : integer;
begin
// Configura a gestão de risco no primeiro tick da primeira
// barra do dia. Necessário agora que tem roteamento no tick
// SNIPPET de "Identificação do primeiro candle de cada dia"
// +
// SNIPPET de "Identificação do primeiro tick de uma barra"
if (Date() <> iDataAtual) then
begin
iDataAtual := Date();
bPrimeiraBarraDoDia := true;
end;
if bPrimeiraBarraDoDia then
begin
bPrimeiraBarraDoDia := false;
if (pTempoReal and LastBarOnChart) or not pTempoReal then
if (CurrentBar <> iBarraAtual) then
begin
iBarraAtual := CurrentBar;
bPrimeiroTickDaBarra := true;
end
else
bPrimeiroTickDaBarra := false;
if bPrimeiroTickDaBarra then
begin
//Faz alguma coisa no primeiro tick da barra
//Aplicável apenas em execução de tempo real
fObjetivoAtualGanho := pObjetivoGanhoDiario;
fLimiteAtualPerda := pLimitePerdaDiaria;
fNovaReferencia := 0;
end;
end;
//-----------------------------------------------------------
// SNIPPET de "Como limitar trades por objetivo de ganho ou limite de perda"
// Resultado até o momento no dia (fechado + aberto)
fResultado := DailyResult(true);
plot(fResultado);
SetPlotStyle(1,psDash);
SetPlotColor(1,clGray);
SetPlotType(1,igHistogram);
plot2(fNovaReferencia - fLimiteAtualPerda);
SetPlotStyle(2,psSolid);
SetPlotColor(2,clRed);
SetPlotWidth(2,3);
// Estratégia qualquer de operação!!!
// Estratégias apenas opera se resultado do dia não
// tiver atingido objetivo de ganho ou limite de perda
fResultadoDiario := DailyResult(true) - fNovaReferencia;
if (fResultadoDiario > -1*fLimiteAtualPerda)
and (fResultadoDiario < fObjetivoAtualGanho) then
begin
// SIMULAÇÃO DE ORDENS PARA FINS DE EXEMPLO
for iHora := 0 to 8 do
begin
if (Time = (0900 + iHora*100)) or (Time = (0930 + iHora*100)) then
if random(2) = 0 then BuyAtMarket else SellShortAtMarket;
if (Time = (0920 + iHora*100)) Or (Time = (0950 + iHora*100)) then
ClosePosition;
end;
end
//Se resultado excedeu objetivo de ganho cria-se novos limites
//Se atingiu limite de perda ou proteção de ganho então para de operar
else
begin
if fResultadoDiario <= -1*pLimitePerdaDiaria then
begin
if hasPosition then ClosePosition;
end
else
if fResultadoDiario >= pObjetivoGanhoDiario then
begin
fNovaReferencia := fNovaReferencia + pObjetivoGanhoDiario;
fLimiteAtualPerda := (pObjetivoGanhoDiario - pProtecaoGanho);
end;
end;
end;
Identificando resultado da última operação
O código abaixo apresenta um exemplo de programação para identificar o resultado da última operação realizada. Assim, o trader pode realizar outras lógicas de limitação de sequência de trades com prejuízo, lucro e outras que desejar.
var
bHasPosition: boolean;
iDia: integer;
fResultadoFechadoDia, fResultadoTotalDia: float;
fResultadoUltimoTrade, fResultadoAberto: float;
begin
if (Date <> iDia) then
begin
iDia := Date;
fResultadoUltimoTrade := 0;
end;
// ARMAZENAMENTO DE VARIÁVEIS (FACILITA A DEPURAÇÃO)
bHasPosition := HasPosition;
fResultadoTotalDia := DailyResult(true);
fResultadoFechadoDia := DailyResult(false);
// CALCULA O RESULTADO ABERTO
if bHasPosition
then fResultadoAberto := fResultadoTotalDia - fResultadoFechadoDia
else fResultadoAberto := 0;
// CALCULA O RESULTADO DO ÚLTIMO TRADE
if not bHasPosition and bHasPosition[1]
then fResultadoUltimoTrade := fResultadoAberto[1];
// PLOTA GRÁFICO PARA INSPEÇÃO VISUAL
plot(fResultadoAberto);
SetPlotType(1,igHistogram);
if fResultadoAberto > 0 then SetPlotColor(1,clGreen)
else if fResultadoAberto < 0 then SetPlotColor(1,clRed)
else SetPlotColor(1,clGray);
plot2(fResultadoUltimoTrade);
SetPlotColor(2,clWhite);
SetPlotStyle(2,psDash);
SetPlotWidth(2,2);
//ROTEAMENTO DE ORDENS
if (Time = 0905) then BuyAtMarket;
if (Time >= 0915) then ClosePosition;
end;
Como obter o preço médio executado durante montagem e realização parcial
É tarefa comum quando você está com um setup de montagem e realizações parciais querer estabelecer ordens de alvo e stop de acordo com o preço executado da última ordem e não do preço médio da posição.
É possível obter esse valor pelo código abaixo. No entanto, é importante ressaltar que devido às limitações da linguagem NTSL, caso haja várias execuções de ordens na mesma barra, o preço calculado de execução será o preço médio das ordens executadas na barra tendo em vista a diferença da posição.
var
iPosicao: integer;
fPrecoMedio: float;
fPrecoExecutado: float;
// ----------------------------------------------------------------------------------------
function getAvgFilledOrderPrice(previousPos: integer; previousPrice: Float;
currentPos:integer; currentPrice: Float): float;
begin
if (currentPos <> 0) and (previousPos <> 0)
and (currentPos <> previousPos) then
begin
Result := (currentPos*currentPrice - previousPos*previousPrice)/(currentPos - previousPos);
end
else
Result := 0;
end;
// ----------------------------------------------------------------------------------------
begin
// Como calcular preço médio de execução de ordens na barra
iPosicao := Position;
fPrecoMedio := Price;
fPrecoExecutado := getAvgFilledOrderPrice(iPosicao[1], fPrecoMedio[1], iPosicao, fPrecoMedio);
plot2(fPrecoExecutado);
SetPlotType(2,igHistogram);
// ---------------------------------------------------------
if (Date = LastCalcDate) and (Time = 1500) then
SellShortAtMarket(2);
if (Date = LastCalcDate) and (Time = 1505) then
BuyAtMarket(1);
if (Date = LastCalcDate) and (Time = 1515) then
SellShortAtMarket(2);
if (Date = LastCalcDate) and (Time = 1530) then
SellShortAtMarket(2);
if (Time >= 1630) and hasPosition then ClosePosition;
if hasPosition then Plot(Price);
SetPlotColor(1, clWhite);
SetPlotStyle(1, psDash);
end;
Bom dia
Pode me ajudar como posso fazer a construção de duas variáveis pra realizar entradas na operação. Ex se hilo der condição e media der condição aí efetua a compra/Venda
Obrigado