Advertisement
Guest User

ProfitChaseStopTrailUnmanagedExample

a guest
Aug 3rd, 2021
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 13.29 KB | None | 0 0
  1. #region Using declarations
  2. using System;
  3. using System.Collections.Generic;
  4. using System.ComponentModel;
  5. using System.ComponentModel.DataAnnotations;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows;
  10. using System.Windows.Input;
  11. using System.Windows.Media;
  12. using System.Xml.Serialization;
  13. using NinjaTrader.Cbi;
  14. using NinjaTrader.Gui;
  15. using NinjaTrader.Gui.Chart;
  16. using NinjaTrader.Gui.SuperDom;
  17. using NinjaTrader.Gui.Tools;
  18. using NinjaTrader.Data;
  19. using NinjaTrader.NinjaScript;
  20. using NinjaTrader.Core.FloatingPoint;
  21. using NinjaTrader.NinjaScript.Indicators;
  22. using NinjaTrader.NinjaScript.DrawingTools;
  23. #endregion
  24.  
  25. //This namespace holds Strategies in this folder and is required. Do not change it.
  26. namespace NinjaTrader.NinjaScript.Strategies
  27. {
  28.     public class ProfitChaseStopTrailUnmanagedExample : Strategy
  29.     {
  30.         #region Variables
  31.         private double              currentPtPrice, currentSlPrice, tickSizeSecondary;
  32.         private Order               entryOrder, exitFlat, exitSession;
  33.         private Order               placeHolderOrder, profitTarget, stopLoss;
  34.         private bool                exitOnCloseWait, ordersCancelled, suppressCancelExit;
  35.         private string              entryName, exitName, ptName, slName, message, ocoString;
  36.         private SessionIterator     sessionIterator;
  37.         #endregion
  38.  
  39.         protected override void OnStateChange()
  40.         {
  41.             if (State == State.SetDefaults)
  42.             {
  43.                 Description                                 = @"";
  44.                 Name                                        = "ProfitChaseStopTrailUnmanagedExample";
  45.                 Calculate                                   = Calculate.OnBarClose;
  46.                 EntriesPerDirection                         = 1;
  47.                 EntryHandling                               = EntryHandling.AllEntries;
  48.                 IsExitOnSessionCloseStrategy                = true;
  49.                 ExitOnSessionCloseSeconds                   = 30;
  50.                 IsFillLimitOnTouch                          = false;
  51.                 TraceOrders                                 = true;
  52.                 BarsRequiredToTrade                         = 1;
  53.                 IsInstantiatedOnEachOptimizationIteration   = false;
  54.                 IsUnmanaged                                 = true;
  55.  
  56.                 ChaseProfitTarget                           = true;
  57.                 PrintDetails                                = false;
  58.                 ProfitTargetDistance                        = 10;
  59.                 StopLossDistance                            = 10;
  60.                 TrailStopLoss                               = true;
  61.                 UseProfitTarget                             = true;
  62.                 UseStopLoss                                 = true;
  63.             }
  64.             else if (State == State.Configure)
  65.             {
  66.                 TraceOrders             = PrintDetails;
  67.  
  68.                 AddDataSeries(BarsPeriodType.Tick, 1);
  69.             }
  70.             else if (State == State.Historical)
  71.             {
  72.                 if (PrintDetails)
  73.                     ClearOutputWindow();
  74.  
  75.                 sessionIterator         = new SessionIterator(Bars);
  76.                 currentPtPrice          = 0;
  77.                 currentSlPrice          = 0;
  78.                 entryName               = string.Empty;
  79.                 exitName                = string.Empty;
  80.                 message                 = string.Empty;
  81.                 ptName                  = string.Empty;
  82.                 slName                  = string.Empty;
  83.                 exitOnCloseWait         = false;
  84.                 suppressCancelExit      = false;
  85.                 placeHolderOrder        = new Order();
  86.                 tickSizeSecondary       = BarsArray[1].Instrument.MasterInstrument.TickSize;
  87.             }
  88.         }
  89.  
  90.         private void AssignOrderToVariable(ref Order order)
  91.         {
  92.             // Assign Order variable in OnOrderUpdate() to ensure the assignment occurs when expected.
  93.             // This is more reliable than assigning Order objects in OnBarUpdate, as the assignment is not guaranteed to be complete if it is referenced immediately after submitting
  94.  
  95.             //if (PrintDetails)
  96.             //  Print(string.Format("{0} | assigning {1} to variable", Times[1][0], order.Name));
  97.  
  98.             if (order.Name == "entry" && entryOrder != order)
  99.                 entryOrder = order;
  100.  
  101.             if (order.Name == "profit target" && profitTarget != order)
  102.                 profitTarget = order;
  103.  
  104.             if (order.Name == "stop loss" && stopLoss != order)
  105.                 stopLoss = order;
  106.  
  107.             if (order.Name == exitName && exitFlat != order)
  108.                 exitFlat = order;
  109.  
  110.             if (order.Name == "Exit on session close" && exitSession != order)
  111.                 exitSession = order;
  112.         }
  113.  
  114.         protected override void OnBarUpdate()
  115.         {
  116.             if (CurrentBars[0] < BarsRequiredToTrade || CurrentBars[1] < BarsRequiredToTrade)
  117.                 return;
  118.  
  119.             if (BarsInProgress == 0)
  120.                 sessionIterator.GetNextSession(Time[0], true);
  121.  
  122.             // if after the exit on close, prevent new orders until the new session
  123.             if (Times[1][0] >= sessionIterator.ActualSessionEnd.AddSeconds(-ExitOnSessionCloseSeconds) && Times[1][0] <= sessionIterator.ActualSessionEnd)
  124.             {
  125.                 exitOnCloseWait = true;
  126.             }
  127.            
  128.             // an exit on close occurred in the previous session, reset for a new entry on the first bar of a new session
  129.             if (exitOnCloseWait && Bars.IsFirstBarOfSession)
  130.             {
  131.                 entryOrder          = null;
  132.                 profitTarget        = null;
  133.                 stopLoss            = null;
  134.                 exitFlat            = null;
  135.                 exitSession         = null;
  136.                 exitOnCloseWait     = false;
  137.                 suppressCancelExit  = false;
  138.             }
  139.  
  140.             // the entry logic can be done when the primary series is processing
  141.             if (BarsInProgress == 0)
  142.             {
  143.                 // because this is a demonstration, this code will cause any historical position
  144.                 // to be exited on the last historical bar so the strategy will always start flat in real-time
  145.                 if (State == State.Historical && CurrentBar == BarsArray[0].Count - 2)
  146.                 {
  147.                     if (entryOrder != null)
  148.                     {
  149.                         if (profitTarget != null && (profitTarget.OrderState == OrderState.Accepted || profitTarget.OrderState == OrderState.Working))
  150.                             CancelOrder(profitTarget);
  151.  
  152.                         else if (stopLoss != null && (stopLoss.OrderState == OrderState.Accepted || stopLoss.OrderState == OrderState.Working))
  153.                             CancelOrder(stopLoss);
  154.  
  155.                         ordersCancelled     = false;
  156.                         suppressCancelExit  = true;
  157.  
  158.                         exitName            = "exit to start flat";
  159.                         exitFlat            = placeHolderOrder;
  160.                         SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.Market, 1, 0, 0, string.Empty, exitName);
  161.                     }
  162.                 }
  163.                 // if this is not the last historical bar, and entryOrder is null, then place an entry order
  164.                 else if (!exitOnCloseWait && entryOrder == null && profitTarget == null && stopLoss == null)
  165.                 {
  166.                     entryName           = "entry";
  167.                     entryOrder          = placeHolderOrder;
  168.                     SubmitOrderUnmanaged(1, OrderAction.Buy, OrderType.Market, 1, 0, 0, string.Empty, entryName);
  169.                 }
  170.             }
  171.  
  172.             // all code below this point takes places during BarsInProgress 1 when the secondary series is processing
  173.             if (BarsInProgress != 1)
  174.                 return;
  175.  
  176.             if (ordersCancelled)
  177.             {
  178.                 message = string.Format("{0} stop and/or target cancelled or rejected", Times[1][0]);
  179.  
  180.                 if (entryOrder == null || entryOrder.OrderState != OrderState.Filled && PrintDetails)
  181.                     Print(string.Format("{0} | OBU | entry not filled or is null", Times[1][0]));
  182.  
  183.                 // if the orders were cancelled due to the exit on close, do not submit an order to flatten
  184.                 if (!exitOnCloseWait && !suppressCancelExit && entryOrder != null && entryOrder.OrderState == OrderState.Filled)
  185.                 {
  186.                     message     += "; exiting and resetting";
  187.                     if (PrintDetails)
  188.                         Print(message);
  189.  
  190.                     exitName    = "exit for cancel";
  191.                     exitFlat    = placeHolderOrder;
  192.                     SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.Market, entryOrder.Filled, 0, 0, string.Empty, exitName);
  193.                 }
  194.  
  195.                 ordersCancelled = false;
  196.                 return;
  197.             }
  198.            
  199.             // the profitTarget/stopLoss is first created when the entry order fills. If it exists then move it.
  200.  
  201.             // trigger the chase action when the current price is further than the set distance to the profit target
  202.             if (ChaseProfitTarget &&
  203.                 profitTarget != null && (profitTarget.OrderState == OrderState.Accepted || profitTarget.OrderState == OrderState.Working) &&
  204.                 Close[0] < currentPtPrice - ProfitTargetDistance * tickSizeSecondary)
  205.             {
  206.                 currentPtPrice  = Close[0] + ProfitTargetDistance * tickSizeSecondary;
  207.                 ChangeOrder(profitTarget, entryOrder.Filled, currentPtPrice, 0);
  208.             }
  209.  
  210.             // trigger the trail action when the current price is further than the set distance to the stop loss
  211.             if (TrailStopLoss &&
  212.                 stopLoss != null && (stopLoss.OrderState == OrderState.Accepted || stopLoss.OrderState == OrderState.Working) &&
  213.                 Close[0] > currentSlPrice + StopLossDistance * tickSizeSecondary)
  214.             {
  215.                 currentSlPrice  = Close[0] - StopLossDistance * tickSizeSecondary;
  216.                 ChangeOrder(stopLoss, entryOrder.Filled, 0, currentSlPrice);
  217.             }
  218.         }
  219.  
  220.         protected override void OnExecutionUpdate(Cbi.Execution execution, string executionId, double price, int quantity,
  221.             Cbi.MarketPosition marketPosition, string orderId, DateTime time)
  222.         {
  223.             if (PrintDetails)
  224.                 Print(string.Format("{0} | OEU | execution | {1} | {2}", Times[1][0], time, execution.ToString()));
  225.  
  226.             if (execution.Order.OrderState != OrderState.Filled)
  227.                 return;
  228.  
  229.             // when the entry order fully fills, place the profit target and stop loss
  230.             if (entryOrder != null && execution.Order == entryOrder)
  231.             {
  232.                 ocoString = Guid.NewGuid().ToString();
  233.  
  234.                 if (UseProfitTarget)
  235.                 {
  236.                     if (PrintDetails)
  237.                         Print(string.Format("{0} | OEU | placing profit target", execution.Time));
  238.  
  239.                     // calculate  a price for the profit target using the secondary series ticksize
  240.                     currentPtPrice  = execution.Order.AverageFillPrice + ProfitTargetDistance * tickSizeSecondary;
  241.                     profitTarget    = placeHolderOrder;
  242.                     SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.Limit, execution.Order.Filled, currentPtPrice, 0, ocoString, "profit target");
  243.                 }
  244.  
  245.                 if (UseStopLoss)
  246.                 {
  247.                     if (PrintDetails)
  248.                         Print(string.Format("{0} | OEU | placing stop loss", execution.Time));
  249.  
  250.                     currentSlPrice  = execution.Order.AverageFillPrice - StopLossDistance * tickSizeSecondary;
  251.                     stopLoss        = placeHolderOrder;
  252.                     SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.StopMarket, execution.Order.Filled, 0, currentSlPrice, ocoString, "stop loss");
  253.                 }
  254.             }
  255.         }
  256.  
  257.         protected override void OnOrderUpdate(Cbi.Order order, double limitPrice, double stopPrice,
  258.             int quantity, int filled, double averageFillPrice,
  259.             Cbi.OrderState orderState, DateTime time, Cbi.ErrorCode error, string comment)
  260.         {
  261.             if (PrintDetails)
  262.                 Print(string.Format("{0} | OOU | order | {1} | {2}", Times[1][0], time, order.ToString()));
  263.  
  264.             AssignOrderToVariable(ref order);
  265.  
  266.             // if either the profit target or stop loss is cancelled or rejected, then reset for a new entry
  267.             if ( !suppressCancelExit && entryOrder != null && order != entryOrder &&
  268.                 (!UseProfitTarget || (profitTarget != null &&
  269.                         (profitTarget.OrderState == OrderState.Cancelled ||
  270.                             profitTarget.OrderState == OrderState.Rejected))) &&
  271.                 (!UseStopLoss || (stopLoss != null &&
  272.                         (stopLoss.OrderState == OrderState.Cancelled ||
  273.                             stopLoss.OrderState == OrderState.Rejected)) )
  274.                 )
  275.             {
  276.                 // if either the stop or target is cancelled, wait 1 tick in OBU to check
  277.                 // to see if this was because of the Exit on close occurring or if manually cancelled
  278.                 ordersCancelled = true;
  279.  
  280.                 if (PrintDetails)
  281.                     Print(string.Format("{0} stop or target cancelled or rejected", Times[1][0]));
  282.             }
  283.            
  284.             // once the stop loss or profit target (or exit for flat / exit for manual cancel) fills, reset for a new entry
  285.             if ( (profitTarget != null && profitTarget.OrderState == OrderState.Filled && (stopLoss == null || stopLoss.OrderState == OrderState.Cancelled)) ||
  286.                 (stopLoss != null && stopLoss.OrderState == OrderState.Filled && (profitTarget == null || profitTarget.OrderState == OrderState.Cancelled)) ||
  287.                 (exitFlat != null && exitFlat.OrderState == OrderState.Filled && (profitTarget == null || profitTarget.OrderState == OrderState.Cancelled) && (stopLoss == null || stopLoss.OrderState == OrderState.Cancelled)) )
  288.             {
  289.                 if (PrintDetails)
  290.                     Print(string.Format( "{0} | OOU | resetting", Times[1][0] ));
  291.  
  292.                 entryOrder          = null;
  293.                 profitTarget        = null;
  294.                 stopLoss            = null;
  295.                 exitFlat            = null;
  296.                 suppressCancelExit  = false;
  297.             }
  298.  
  299.             // when the Exit on close fills, wait for the new session to start the next entry
  300.             // (so no orders are submitted between the exit on close and the end of the session)
  301.             if (exitSession != null && exitSession.OrderState == OrderState.Filled)
  302.             {
  303.                 if (PrintDetails)
  304.                     Print(string.Format("{0} | OOU | exit on close filled waiting for next session for reset\r\n{1}", Times[1][0], order.ToString()));
  305.  
  306.                 exitOnCloseWait = true;
  307.             }
  308.         }
  309.  
  310.         #region Properties
  311.         [NinjaScriptProperty]
  312.         [Display(Name = "Chase profit target", Order = 2, GroupName = "NinjaScriptStrategyParameters")]
  313.         public bool ChaseProfitTarget
  314.         { get; set; }
  315.  
  316.         [NinjaScriptProperty]
  317.         [Range(1, int.MaxValue)]
  318.         [Display(Name = "Profit target distance", Description = "Distance for profit target (in ticks)", Order = 3, GroupName = "NinjaScriptStrategyParameters")]
  319.         public int ProfitTargetDistance
  320.         { get; set; }
  321.  
  322.         [NinjaScriptProperty]
  323.         [Display(Name = "Print details", Order = 7, GroupName = "NinjaScriptStrategyParameters")]
  324.         public bool PrintDetails
  325.         { get; set; }
  326.  
  327.         [NinjaScriptProperty]
  328.         [Range(1, int.MaxValue)]
  329.         [Display(Name = "Stop loss distance", Description = "Distance for stop loss (in ticks)", Order = 6, GroupName = "NinjaScriptStrategyParameters")]
  330.         public int StopLossDistance
  331.         { get; set; }
  332.  
  333.         [NinjaScriptProperty]
  334.         [Display(Name = "Trail stop loss", Order = 5, GroupName = "NinjaScriptStrategyParameters")]
  335.         public bool TrailStopLoss
  336.         { get; set; }
  337.  
  338.         [NinjaScriptProperty]
  339.         [Display(Name = "Use profit target", Order = 1, GroupName = "NinjaScriptStrategyParameters")]
  340.         public bool UseProfitTarget
  341.         { get; set; }
  342.  
  343.         [NinjaScriptProperty]
  344.         [Display(Name = "Use stop loss", Order = 4, GroupName = "NinjaScriptStrategyParameters")]
  345.         public bool UseStopLoss
  346.         { get; set; }
  347.         #endregion
  348.  
  349.     }
  350. }
  351.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement