Lean  $LEAN_TAG$
TrailingStopOrder.cs
1 /*
2  * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3  * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14 */
15 
16 using System;
17 using Newtonsoft.Json;
19 
20 namespace QuantConnect.Orders
21 {
22  /// <summary>
23  /// Trailing Stop Order Type Definition
24  /// </summary>
26  {
27  /// <summary>
28  /// Trailing amount for this trailing stop order
29  /// </summary>
30  [JsonProperty(PropertyName = "trailingAmount")]
31  public decimal TrailingAmount { get; internal set; }
32 
33  /// <summary>
34  /// Determines whether the <see cref="TrailingAmount"/> is a percentage or an absolute currency value
35  /// </summary>
36  [JsonProperty(PropertyName = "trailingAsPercentage")]
37  public bool TrailingAsPercentage { get; internal set; }
38 
39  /// <summary>
40  /// StopLimit Order Type
41  /// </summary>
42  public override OrderType Type
43  {
44  get { return OrderType.TrailingStop; }
45  }
46 
47  /// <summary>
48  /// Default constructor for JSON Deserialization:
49  /// </summary>
51  {
52  }
53 
54  /// <summary>
55  /// New Trailing Stop Market Order constructor
56  /// </summary>
57  /// <param name="symbol">Symbol asset being traded</param>
58  /// <param name="quantity">Quantity of the asset to be traded</param>
59  /// <param name="stopPrice">Initial stop price at which the order should be triggered</param>
60  /// <param name="trailingAmount">The trailing amount to be used to update the stop price</param>
61  /// <param name="trailingAsPercentage">Whether the <paramref name="trailingAmount"/> is a percentage or an absolute currency value</param>
62  /// <param name="time">Time the order was placed</param>
63  /// <param name="tag">User defined data tag for this order</param>
64  /// <param name="properties">The properties for this order</param>
65  public TrailingStopOrder(Symbol symbol, decimal quantity, decimal stopPrice, decimal trailingAmount, bool trailingAsPercentage,
66  DateTime time, string tag = "", IOrderProperties properties = null)
67  : base(symbol, quantity, stopPrice, time, tag, properties)
68  {
69  TrailingAmount = trailingAmount;
70  TrailingAsPercentage = trailingAsPercentage;
71  }
72 
73  /// <summary>
74  /// New Trailing Stop Market Order constructor.
75  /// It creates a new Trailing Stop Market Order with an initial stop price calculated by subtracting (for a sell) or adding (for a buy) the
76  /// trailing amount to the current market price.
77  /// </summary>
78  /// <param name="symbol">Symbol asset being traded</param>
79  /// <param name="quantity">Quantity of the asset to be traded</param>
80  /// <param name="trailingAmount">The trailing amount to be used to update the stop price</param>
81  /// <param name="trailingAsPercentage">Whether the <paramref name="trailingAmount"/> is a percentage or an absolute currency value</param>
82  /// <param name="time">Time the order was placed</param>
83  /// <param name="tag">User defined data tag for this order</param>
84  /// <param name="properties">The properties for this order</param>
85  public TrailingStopOrder(Symbol symbol, decimal quantity, decimal trailingAmount, bool trailingAsPercentage,
86  DateTime time, string tag = "", IOrderProperties properties = null)
87  : this(symbol, quantity, 0, trailingAmount, trailingAsPercentage, time, tag, properties)
88  {
89  }
90 
91  /// <summary>
92  /// Gets the default tag for this order
93  /// </summary>
94  /// <returns>The default tag</returns>
95  public override string GetDefaultTag()
96  {
97  return Messages.TrailingStopOrder.Tag(this);
98  }
99 
100  /// <summary>
101  /// Modifies the state of this order to match the update request
102  /// </summary>
103  /// <param name="request">The request to update this order object</param>
104  public override void ApplyUpdateOrderRequest(UpdateOrderRequest request)
105  {
106  base.ApplyUpdateOrderRequest(request);
107  if (request.TrailingAmount.HasValue)
108  {
109  TrailingAmount = request.TrailingAmount.Value;
110  }
111  }
112 
113  /// <summary>
114  /// Returns a string that represents the current object.
115  /// </summary>
116  /// <returns>
117  /// A string that represents the current object.
118  /// </returns>
119  /// <filterpriority>2</filterpriority>
120  public override string ToString()
121  {
122  return Messages.TrailingStopOrder.ToString(this);
123  }
124 
125  /// <summary>
126  /// Creates a deep-copy clone of this order
127  /// </summary>
128  /// <returns>A copy of this order</returns>
129  public override Order Clone()
130  {
131  var order = new TrailingStopOrder
132  {
136  };
137  CopyTo(order);
138  return order;
139  }
140 
141  /// <summary>
142  /// Tries to update the stop price for a trailing stop order given the current market price
143  /// </summary>
144  /// <param name="currentMarketPrice">The current market price</param>
145  /// <param name="currentStopPrice">The current trailing stop order stop price</param>
146  /// <param name="trailingAmount">The trailing amount to be used to update the stop price</param>
147  /// <param name="trailingAsPercentage">Whether the <paramref name="trailingAmount"/> is a percentage or an absolute currency value</param>
148  /// <param name="direction">The order direction</param>
149  /// <param name="updatedStopPrice">The updated stop price</param>
150  /// <returns>
151  /// Whether the stop price was updated.
152  /// This only happens when the distance between the current stop price and the current market price is greater than the trailing amount,
153  /// which will happen when the market price raises/falls for sell/buy orders respectively.
154  /// </returns>
155  public static bool TryUpdateStopPrice(decimal currentMarketPrice, decimal currentStopPrice, decimal trailingAmount,
156  bool trailingAsPercentage, OrderDirection direction, out decimal updatedStopPrice)
157  {
158  updatedStopPrice = 0m;
159  var distanceToMarketPrice = direction == OrderDirection.Sell
160  ? currentMarketPrice - currentStopPrice
161  : currentStopPrice - currentMarketPrice;
162  var stopReference = trailingAsPercentage ? currentMarketPrice * trailingAmount : trailingAmount;
163 
164  if (distanceToMarketPrice <= stopReference)
165  {
166  return false;
167  }
168 
169  updatedStopPrice = CalculateStopPrice(currentMarketPrice, trailingAmount, trailingAsPercentage, direction);
170  return true;
171  }
172 
173  /// <summary>
174  /// Calculates the stop price for a trailing stop order given the current market price
175  /// </summary>
176  /// <param name="currentMarketPrice">The current market price</param>
177  /// <param name="trailingAmount">The trailing amount to be used to update the stop price</param>
178  /// <param name="trailingAsPercentage">Whether the <paramref name="trailingAmount"/> is a percentage or an absolute currency value</param>
179  /// <param name="direction">The order direction</param>
180  /// <returns>The stop price for the order given the current market price</returns>
181  public static decimal CalculateStopPrice(decimal currentMarketPrice, decimal trailingAmount, bool trailingAsPercentage,
182  OrderDirection direction)
183  {
184  if (trailingAsPercentage)
185  {
186  return direction == OrderDirection.Buy
187  ? currentMarketPrice * (1 + trailingAmount)
188  : currentMarketPrice * (1 - trailingAmount);
189  }
190 
191  return direction == OrderDirection.Buy
192  ? currentMarketPrice + trailingAmount
193  : currentMarketPrice - trailingAmount;
194  }
195  }
196 }