Snippets para Ordens e Administração de Trade
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 rotear ordens de maneira fácil (Modo gerenciado)?
A NinjaTrader possui em seu NinjaScript uma camada de abstração para envio e gestão de ordens. Este modo é chamado de modo gerenciado e seu funcionamento torna bem simples a implementação de estratégias para iniciantes e até mesmo pessoas com conhecimento intermediário.
No modo gerenciado, as ordens são válidas apenas até o próximo candle/barra, o que simplifica a gestão de ordens abertas e cancelamentos. E também há diversos controles que reduzem a chance de problemas na administração da posição da estratégia.
Veja abaixo um exemplo do envio de ordens em NinjaScript utilizando o modo gerenciado.
#region Using declarations
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.Indicators;
using NinjaTrader.NinjaScript.DrawingTools;
#endregion
//This namespace holds Strategies in this folder and is required. Do not change it.
namespace NinjaTrader.NinjaScript.Strategies
{
public class TestingOrdersStrategy : Strategy
{
private TimeSpan tsOpen;
private TimeSpan tsClose;
private Order myOrder;
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = @"Enter the description for your new custom Strategy here.";
Name = "TestingOrdersStrategy";
Calculate = Calculate.OnBarClose;
EntriesPerDirection = 1;
EntryHandling = EntryHandling.AllEntries;
IsExitOnSessionCloseStrategy = true;
ExitOnSessionCloseSeconds = 30;
IsFillLimitOnTouch = false;
MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
OrderFillResolution = OrderFillResolution.Standard;
Slippage = 0;
StartBehavior = StartBehavior.WaitUntilFlat;
TimeInForce = TimeInForce.Gtc;
TraceOrders = false;
RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
StopTargetHandling = StopTargetHandling.PerEntryExecution;
BarsRequiredToTrade = 20;
// Disable this property for performance gains in Strategy Analyzer optimizations
// See the Help Guide for additional information
IsInstantiatedOnEachOptimizationIteration = true;
PositionOpeningTime = DateTime.Parse("10:30", System.Globalization.CultureInfo.InvariantCulture);
PositionClosingTime = DateTime.Parse("10:36", System.Globalization.CultureInfo.InvariantCulture);
}
else if (State == State.Configure)
{
tsOpen = new TimeSpan(PositionOpeningTime.Hour, PositionOpeningTime.Minute, 0);
tsClose = new TimeSpan(PositionClosingTime.Hour, PositionClosingTime.Minute, 0);
}
}
protected override void OnBarUpdate()
{
//Match real-time order object based on a historical order object (run just once)
if (myOrder != null && myOrder.IsBacktestOrder && State == State.Realtime)
myOrder = GetRealtimeOrder(myOrder);
//Open position at specified time (tsOpen)
if ((Time[0].TimeOfDay == tsOpen) && (Position.MarketPosition == MarketPosition.Flat))
{
myOrder = EnterLong("openingSignal");
//myOrder = EnterLongLimit(4451.25, "openingSignal");
//myOrder = EnterLongStopMarket(4454.50, "openingSignal");
//This will not open position, since the price reach that price a few bars after the order was submitted (Managed orders)
//myOrder = EnterLongLimit(4450, "openingSignal");
//This will not open position, since the price reach that price only 2 bars after the order was submitted (Managed orders)
//myOrder = EnterLongStopMarket(4455, "openingSignal");
}
//Close position at specified time (tsClose)
if (Time[0].TimeOfDay == tsClose)
{
if (Position.MarketPosition == MarketPosition.Long) { ExitLong("openingSignal"); }
if (Position.MarketPosition == MarketPosition.Short) { ExitShort("openingSignal"); }
}
}
#region Properties
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="OpeningTIime", Order=1, GroupName="Parameters")]
public DateTime PositionOpeningTime
{ get; set; }
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="ClosingTime", Order=2, GroupName="Parameters")]
public DateTime PositionClosingTime
{ get; set; }
#endregion
}
}
Como fazer Gestão de Risco das operações de maneira simples (Stoploss/TakeProfit)?
No âmbito da camada de abstração do NinjaScript, existem algumas funções que facilitam bastante a adoção de práticas de gestão de risco para operações no código fonte.
Veja abaixo duas formas de definir o stoploss e alvo (take profit) das operações de maneira estática, ou seja, fixa durante toda a execução da estratégia, ou de maneira dinâmica, ajustando o risco de acordo com as condições do mercado.
Gestão de risco estática
Nesta situação, os parâmetros para o stoploss e alvo das operações são definidos na transição para o estado Configure da estratégia, podendo inclusive, serem utilizados parâmetros de entrada para fins de otimização futura.
#region Using declarations
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.Indicators;
using NinjaTrader.NinjaScript.DrawingTools;
#endregion
//This namespace holds Strategies in this folder and is required. Do not change it.
namespace NinjaTrader.NinjaScript.Strategies
{
public class TestingOpRiskManagement : Strategy
{
private TimeSpan tsOpen;
private TimeSpan tsClose;
private Order myOrder;
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = @"Enter the description for your new custom Strategy here.";
Name = "TestingOpRiskManagement";
Calculate = Calculate.OnBarClose;
EntriesPerDirection = 1;
EntryHandling = EntryHandling.AllEntries;
IsExitOnSessionCloseStrategy = true;
ExitOnSessionCloseSeconds = 30;
IsFillLimitOnTouch = false;
MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
OrderFillResolution = OrderFillResolution.Standard;
Slippage = 0;
StartBehavior = StartBehavior.WaitUntilFlat;
TimeInForce = TimeInForce.Gtc;
TraceOrders = false;
RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
StopTargetHandling = StopTargetHandling.PerEntryExecution;
BarsRequiredToTrade = 20;
// Disable this property for performance gains in Strategy Analyzer optimizations
// See the Help Guide for additional information
IsInstantiatedOnEachOptimizationIteration = true;
PositionOpeningTime = DateTime.Parse("10:30", System.Globalization.CultureInfo.InvariantCulture);
PositionClosingTime = DateTime.Parse("16:00", System.Globalization.CultureInfo.InvariantCulture);
}
else if (State == State.Configure)
{
tsOpen = new TimeSpan(PositionOpeningTime.Hour, PositionOpeningTime.Minute, 0);
tsClose = new TimeSpan(PositionClosingTime.Hour, PositionClosingTime.Minute, 0);
// Static risk management. Stoploss and Target are defined and maintained fixed through the strategy lifetime
SetStopLoss(CalculationMode.Ticks, 20);
//SetTrailStop(CalculationMode.Ticks, 24);
SetProfitTarget(CalculationMode.Ticks, 60);
}
}
protected override void OnBarUpdate()
{
if (myOrder != null && myOrder.IsBacktestOrder && State == State.Realtime)
myOrder = GetRealtimeOrder(myOrder);
//Open position at specified time (tsOpen)
if ((Time[0].TimeOfDay == tsOpen) && (Position.MarketPosition == MarketPosition.Flat))
{
Random rnd = new Random();
if (rnd.Next(0,2) == 0)
myOrder = EnterLong("openingSignal");
else
myOrder = EnterShort("openingSignal");
}
//Close position at specified time (tsClose)
if (Time[0].TimeOfDay == tsClose)
{
if (Position.MarketPosition == MarketPosition.Long) { ExitLong("openingSignal"); }
if (Position.MarketPosition == MarketPosition.Short) { ExitShort("openingSignal"); }
}
}
#region Properties
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="OpeningTIime", Order=1, GroupName="Parameters")]
public DateTime PositionOpeningTime
{ get; set; }
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="ClosingTime", Order=2, GroupName="Parameters")]
public DateTime PositionClosingTime
{ get; set; }
#endregion
}
}
Gestão de risco dinâmica
Nesta situação, os parâmetros para o stoploss e alvo das operações são definidos no método onBarUpdate e a frequencia de atualização dependerá da propriedade da estratégia relacionada a frequência de cálculo. Neste modo, o trader pode utilizar qualquer lógica que desejar, podendo inclusive utilizar indicadores técnicos, a exemplo do ATR (Average True Range).
#region Using declarations
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.Indicators;
using NinjaTrader.NinjaScript.DrawingTools;
#endregion
//This namespace holds Strategies in this folder and is required. Do not change it.
namespace NinjaTrader.NinjaScript.Strategies
{
public class TestingOpRiskManagement : Strategy
{
private TimeSpan tsOpen;
private TimeSpan tsClose;
private Order myOrder;
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = @"Enter the description for your new custom Strategy here.";
Name = "TestingOpRiskManagement";
Calculate = Calculate.OnBarClose;
EntriesPerDirection = 1;
EntryHandling = EntryHandling.AllEntries;
IsExitOnSessionCloseStrategy = true;
ExitOnSessionCloseSeconds = 30;
IsFillLimitOnTouch = false;
MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
OrderFillResolution = OrderFillResolution.Standard;
Slippage = 0;
StartBehavior = StartBehavior.WaitUntilFlat;
TimeInForce = TimeInForce.Gtc;
TraceOrders = false;
RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
StopTargetHandling = StopTargetHandling.PerEntryExecution;
BarsRequiredToTrade = 20;
// Disable this property for performance gains in Strategy Analyzer optimizations
// See the Help Guide for additional information
IsInstantiatedOnEachOptimizationIteration = true;
PositionOpeningTime = DateTime.Parse("10:30", System.Globalization.CultureInfo.InvariantCulture);
PositionClosingTime = DateTime.Parse("16:00", System.Globalization.CultureInfo.InvariantCulture);
}
else if (State == State.Configure)
{
tsOpen = new TimeSpan(PositionOpeningTime.Hour, PositionOpeningTime.Minute, 0);
tsClose = new TimeSpan(PositionClosingTime.Hour, PositionClosingTime.Minute, 0);
// Static risk management. Stoploss and Target are defined and maintained fixed through the strategy lifetime
//SetStopLoss(CalculationMode.Ticks, 20);
//SetTrailStop(CalculationMode.Ticks, 24);
//SetProfitTarget(CalculationMode.Ticks, 60);
}
}
protected override void OnBarUpdate()
{
if (myOrder != null && myOrder.IsBacktestOrder && State == State.Realtime)
myOrder = GetRealtimeOrder(myOrder);
//Open position at specified time (tsOpen)
if ((Time[0].TimeOfDay == tsOpen) && (Position.MarketPosition == MarketPosition.Flat))
{
Random rnd = new Random();
double volatility = Math.Ceiling(ATR(500)[0]/TickSize);
double stoplossTicks = 5*volatility;
double takeProfitTicks = 3*stoplossTicks;
// Dynamic risk management. Stoploss and Target are adapted to market conditions
SetTrailStop(CalculationMode.Ticks, stoplossTicks);
SetProfitTarget(CalculationMode.Ticks, takeProfitTicks);
Print("CurrentBar: " + CurrentBar.ToString() + " - Stoploss: " + stoplossTicks.ToString() + " ticks | Target: "
+ takeProfitTicks.ToString() + " ticks");
if (rnd.Next(0,2) == 0)
myOrder = EnterLong("openingSignal");
else
myOrder = EnterShort("openingSignal");
}
//Close position at specified time (tsClose)
if (Time[0].TimeOfDay == tsClose)
{
if (Position.MarketPosition == MarketPosition.Long) { ExitLong("openingSignal"); }
if (Position.MarketPosition == MarketPosition.Short) { ExitShort("openingSignal"); }
}
}
#region Properties
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="OpeningTIime", Order=1, GroupName="Parameters")]
public DateTime PositionOpeningTime
{ get; set; }
[NinjaScriptProperty]
[PropertyEditor("NinjaTrader.Gui.Tools.TimeEditorKey")]
[Display(Name="ClosingTime", Order=2, GroupName="Parameters")]
public DateTime PositionClosingTime
{ get; set; }
#endregion
}
}