Um backtesting adequado deve buscar simular situações práticas do mercado (slippage, custo de operação, etc...)
Boa Noite,
Estou tentando implementar uma saida parcial no codigo aqui mesmo da comunidade, mas não estou conseguindo, se alguem puder ajudar a idéia e fazer uma parcial e deixar o restante dos lotes sair quando o TraillingStop atintigir o preço.
Codigo da Comunidade
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);
bModuloAutomacao(false);
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;
if Not bModuloAutomacao then
begin
SellToCoverStop(fPrecoStop,fPrecoStopOffset);
if isBought then SellToCoverLimit(fPrecoAlvo);
end
else
begin
SellShortStop(fPrecoStop,fPrecoStopOffset);
if isBought then SellShortLimit(fPrecoAlvo);
end;
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;
if Not bModuloAutomacao then
begin
BuyToCoverStop(fPrecoStop,fPrecoStopOffset);
if isSold then BuyToCoverLimit(fPrecoAlvo);
end
else
begin
BuyStop(fPrecoStop,fPrecoStopOffset);
if isSold then BuyLimit(fPrecoAlvo);
end;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;
Foi postado recentemente neste fórum um código exemplo de saída parcial na qual vc pode adaptar o seu código.
const cTamanhoPosicaoInicial (2); //Define a constante para o tamanho inicial da posição. var bSinalCompra: boolean; bSinalVenda: boolean; fStopCompra, fStopVenda: float; bEstaPosicionado: boolean; fAlvoParcial: float; iTamanhoPosicaoParcial: integer; begin {Busca as Entrada} If Not (IsBought) and (bSinalCompra) then begin fStopCompra := fAlvoParcial := BuyAtMarket(cTamanhoPosicaoInicial); bestaPosicionado := verdadeiro; end; //Verifica ainda não foi aberta uma posição comprada e se o sinal de compra é verdadeiro. Em seguida, define os valores do stop loss e do alvo parcial de lucro, bem como faz uma ordem de compra a mercado para a posição inicial. Por fim, atualiza a variável bestaPosicionado para verdadeiro, indicando que uma posição foi aberta. If Not(IsSold) and ((bSinalVenda) then begin fStopVenda := fAlvoParcial := SellShortAtMarket(cTamanhoPosicaoInicial); bestaPosicionado := verdadeiro; end; //Verifica ainda não foi aberta uma posição vendida e se o sinal de venda é verdadeiro. Atribuí os valores de Stoploss, Alvo e faz a venda, altera a variável bestaPosicionado para verdadeiro, indicando que uma posição foi aberta. {Calcula os valores de saída parcial da compra} if (IsBought) e (bEstaPosicionado) then begin iTamanhoPosicaoParcial := Ceiling(cTamanhoPosicaoInicial / 2); bEstaPosicionado := falso; end; //Se o ativo foi comprado e uma posição foi aberta, calcula o tamanho da posição parcial com base na metade do tamanho da posição inicial. A função Ceiling é usada caso a posição inicial seja um valor impar ex. 3, logo em seguida muda a variável /estaPosicionado para falso, indicando que a posição parcial foi calculada. {Calcula os valores de saída parcial da venda} if (IsSold) e (bEstaPosicionado) then begin iTamanhoPosicaoParcial := Ceiling(cTamanhoPosicaoInicial / 2); bEstaPosicionado := falso; end; //Mesma lógica do bloco anterior para compra. {Busca a saída parcial da compra} If (IsBought) And (Position = cTamanhoPosicaoInicial) then begin SellToCoverLimit(AlvoParcial,tamanhoPosicaoParcial); End; {Busca saída parcial da Venda} If (IsSold) and (Position = neg(iTamanhoPosicaoInicial)) then begin BuyToCoverLimit(fAlvoParcial,iTamanhoPosicaoParcial); end; {Recalcula posicao e ordens de compra} if (IsBought) e (Position < cTamanhoPosicaoInicial) then begin iTamanhoPosicaoParcial := Position; end; //Atribui a variável iTamanhoPosicaoParcial o valor do restante da posicao {Recalcula posição e ordens de venda} //Como a função "Position" retorna um valor negativo é preciso usar a função "neg" if (IsSold) e (Position > neg(iTamanhoPosicaoInicial)) then inicio iTamanhoPosicaoParcial := Position; fim; End;