Lean  $LEAN_TAG$
SecurityHolding.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 QuantConnect.Orders;
20 
22 {
23  /// <summary>
24  /// SecurityHolding is a base class for purchasing and holding a market item which manages the asset portfolio
25  /// </summary>
26  public class SecurityHolding
27  {
28  /// <summary>
29  /// Event raised each time the holdings quantity is changed.
30  /// </summary>
31  public event EventHandler<SecurityHoldingQuantityChangedEventArgs> QuantityChanged;
32 
33  //Working Variables
34  private bool _invested;
35  private decimal _averagePrice;
36  private decimal _quantity;
37  private decimal _price;
38  private decimal _totalSaleVolume;
39  private decimal _profit;
40  private decimal _lastTradeProfit;
41  private decimal _totalFees;
42  private decimal _totalDividends;
43  private readonly Security _security;
44  private readonly ICurrencyConverter _currencyConverter;
45 
46  /// <summary>
47  /// Create a new holding class instance setting the initial properties to $0.
48  /// </summary>
49  /// <param name="security">The security being held</param>
50  /// <param name="currencyConverter">A currency converter instance</param>
51  public SecurityHolding(Security security, ICurrencyConverter currencyConverter)
52  {
53  _security = security;
54  //Total Sales Volume for the day
55  _totalSaleVolume = 0;
56  _lastTradeProfit = 0;
57  _currencyConverter = currencyConverter;
58  }
59 
60  /// <summary>
61  /// Create a new holding class instance copying the initial properties
62  /// </summary>
63  /// <param name="holding">The security being held</param>
64  protected SecurityHolding(SecurityHolding holding)
65  {
66  _security = holding._security;
67  _averagePrice = holding._averagePrice;
68  Quantity = holding._quantity;
69  _price = holding._price;
70  _totalSaleVolume = holding._totalSaleVolume;
71  _profit = holding._profit;
72  _lastTradeProfit = holding._lastTradeProfit;
73  _totalFees = holding._totalFees;
74  _currencyConverter = holding._currencyConverter;
75  }
76 
77  /// <summary>
78  /// The security being held
79  /// </summary>
80  protected Security Security
81  {
82  get
83  {
84  return _security;
85  }
86  }
87 
88  /// <summary>
89  /// Gets the current target holdings for this security
90  /// </summary>
92  {
93  get; set;
94  }
95 
96  /// <summary>
97  /// Average price of the security holdings.
98  /// </summary>
99  public decimal AveragePrice
100  {
101  get
102  {
103  return _averagePrice;
104  }
105  protected set
106  {
107  _averagePrice = value;
108  }
109  }
110 
111  /// <summary>
112  /// Quantity of the security held.
113  /// </summary>
114  /// <remarks>Positive indicates long holdings, negative quantity indicates a short holding</remarks>
115  /// <seealso cref="AbsoluteQuantity"/>
116  public decimal Quantity
117  {
118  get
119  {
120  return _quantity;
121  }
122  protected set
123  {
124  _invested = value != 0;
125  _quantity = value;
126  }
127  }
128 
129  /// <summary>
130  /// Symbol identifier of the underlying security.
131  /// </summary>
132  public Symbol Symbol
133  {
134  get
135  {
136  return _security.Symbol;
137  }
138  }
139 
140  /// <summary>
141  /// The security type of the symbol
142  /// </summary>
143  public SecurityType Type
144  {
145  get
146  {
147  return _security.Type;
148  }
149  }
150 
151  /// <summary>
152  /// Leverage of the underlying security.
153  /// </summary>
154  public virtual decimal Leverage
155  {
156  get
157  {
158  return _security.BuyingPowerModel.GetLeverage(_security);
159  }
160  }
161 
162  /// <summary>
163  /// Acquisition cost of the security total holdings in units of the account's currency.
164  /// </summary>
165  public virtual decimal HoldingsCost
166  {
167  get
168  {
169  if (Quantity == 0)
170  {
171  return 0;
172  }
174  }
175  }
176 
177  /// <summary>
178  /// Unlevered Acquisition cost of the security total holdings in units of the account's currency.
179  /// </summary>
180  public virtual decimal UnleveredHoldingsCost
181  {
182  get { return HoldingsCost/Leverage; }
183  }
184 
185  /// <summary>
186  /// Current market price of the security.
187  /// </summary>
188  public virtual decimal Price
189  {
190  get
191  {
192  return _price;
193  }
194  protected set
195  {
196  _price = value;
197  }
198  }
199 
200  /// <summary>
201  /// Absolute holdings cost for current holdings in units of the account's currency.
202  /// </summary>
203  /// <seealso cref="HoldingsCost"/>
204  public virtual decimal AbsoluteHoldingsCost
205  {
206  get
207  {
208  return Math.Abs(HoldingsCost);
209  }
210  }
211 
212  /// <summary>
213  /// Unlevered absolute acquisition cost of the security total holdings in units of the account's currency.
214  /// </summary>
215  public virtual decimal UnleveredAbsoluteHoldingsCost
216  {
217  get
218  {
219  return Math.Abs(UnleveredHoldingsCost);
220  }
221  }
222 
223  /// <summary>
224  /// Market value of our holdings in units of the account's currency.
225  /// </summary>
226  public virtual decimal HoldingsValue
227  {
228  get
229  {
230  if (Quantity == 0)
231  {
232  return 0;
233  }
234 
236  }
237  }
238 
239  /// <summary>
240  /// Absolute of the market value of our holdings in units of the account's currency.
241  /// </summary>
242  /// <seealso cref="HoldingsValue"/>
243  public virtual decimal AbsoluteHoldingsValue
244  {
245  get { return Math.Abs(HoldingsValue); }
246  }
247 
248  /// <summary>
249  /// Boolean flag indicating if we hold any of the security
250  /// </summary>
251  public virtual bool HoldStock => _invested;
252 
253  /// <summary>
254  /// Boolean flag indicating if we hold any of the security
255  /// </summary>
256  /// <remarks>Alias of HoldStock</remarks>
257  /// <seealso cref="HoldStock"/>
258  public virtual bool Invested => _invested;
259 
260  /// <summary>
261  /// The total transaction volume for this security since the algorithm started in units of the account's currency.
262  /// </summary>
263  public virtual decimal TotalSaleVolume
264  {
265  get { return _totalSaleVolume; }
266  }
267 
268  /// <summary>
269  /// Total fees for this company since the algorithm started in units of the account's currency.
270  /// </summary>
271  public virtual decimal TotalFees
272  {
273  get { return _totalFees; }
274  }
275 
276  /// <summary>
277  /// Total dividends for this company since the algorithm started in units of the account's currency.
278  /// </summary>
279  public virtual decimal TotalDividends
280  {
281  get { return _totalDividends; }
282  }
283 
284  /// <summary>
285  /// Boolean flag indicating we have a net positive holding of the security.
286  /// </summary>
287  /// <seealso cref="IsShort"/>
288  public virtual bool IsLong
289  {
290  get
291  {
292  return Quantity > 0;
293  }
294  }
295 
296  /// <summary>
297  /// BBoolean flag indicating we have a net negative holding of the security.
298  /// </summary>
299  /// <seealso cref="IsLong"/>
300  public virtual bool IsShort
301  {
302  get
303  {
304  return Quantity < 0;
305  }
306  }
307 
308  /// <summary>
309  /// Absolute quantity of holdings of this security
310  /// </summary>
311  /// <seealso cref="Quantity"/>
312  public virtual decimal AbsoluteQuantity
313  {
314  get
315  {
316  return Math.Abs(Quantity);
317  }
318  }
319 
320  /// <summary>
321  /// Record of the closing profit from the last trade conducted in units of the account's currency.
322  /// </summary>
323  public virtual decimal LastTradeProfit
324  {
325  get
326  {
327  return _lastTradeProfit;
328  }
329  }
330 
331  /// <summary>
332  /// Calculate the total profit for this security in units of the account's currency.
333  /// </summary>
334  /// <seealso cref="NetProfit"/>
335  public virtual decimal Profit
336  {
337  get { return _profit + _totalDividends; }
338  }
339 
340  /// <summary>
341  /// Return the net for this company measured by the profit less fees in units of the account's currency.
342  /// </summary>
343  /// <seealso cref="Profit"/>
344  /// <seealso cref="TotalFees"/>
345  public virtual decimal NetProfit
346  {
347  get
348  {
349  return Profit - TotalFees;
350  }
351  }
352 
353  /// <summary>
354  /// Gets the unrealized profit as a percentage of holdings cost
355  /// </summary>
356  public virtual decimal UnrealizedProfitPercent
357  {
358  get
359  {
360  if (AbsoluteHoldingsCost == 0) return 0m;
362  }
363  }
364 
365  /// <summary>
366  /// Unrealized profit of this security when absolute quantity held is more than zero in units of the account's currency.
367  /// </summary>
368  public virtual decimal UnrealizedProfit
369  {
370  get { return TotalCloseProfit(); }
371  }
372 
373  /// <summary>
374  /// Adds a fee to the running total of total fees in units of the account's currency.
375  /// </summary>
376  /// <param name="newFee"></param>
377  public void AddNewFee(decimal newFee)
378  {
379  _totalFees += newFee;
380  }
381 
382  /// <summary>
383  /// Adds a profit record to the running total of profit in units of the account's currency.
384  /// </summary>
385  /// <param name="profitLoss">The cash change in portfolio from closing a position</param>
386  public void AddNewProfit(decimal profitLoss)
387  {
388  _profit += profitLoss;
389  }
390 
391  /// <summary>
392  /// Adds a new sale value to the running total trading volume in units of the account's currency.
393  /// </summary>
394  /// <param name="saleValue"></param>
395  public void AddNewSale(decimal saleValue)
396  {
397  _totalSaleVolume += saleValue;
398  }
399 
400  /// <summary>
401  /// Adds a new dividend payment to the running total dividend in units of the account's currency.
402  /// </summary>
403  /// <param name="dividend"></param>
404  public void AddNewDividend(decimal dividend)
405  {
406  _totalDividends += dividend;
407  }
408 
409  /// <summary>
410  /// Set the last trade profit for this security from a Portfolio.ProcessFill call in units of the account's currency.
411  /// </summary>
412  /// <param name="lastTradeProfit">Value of the last trade profit</param>
413  public void SetLastTradeProfit(decimal lastTradeProfit)
414  {
415  _lastTradeProfit = lastTradeProfit;
416  }
417 
418  /// <summary>
419  /// Set the quantity of holdings and their average price after processing a portfolio fill.
420  /// </summary>
421  public virtual void SetHoldings(decimal averagePrice, int quantity)
422  {
423  SetHoldings(averagePrice, (decimal) quantity);
424  }
425 
426  /// <summary>
427  /// Set the quantity of holdings and their average price after processing a portfolio fill.
428  /// </summary>
429  public virtual void SetHoldings(decimal averagePrice, decimal quantity)
430  {
431  var previousQuantity = _quantity;
432  var previousAveragePrice = _averagePrice;
433 
434  Quantity = quantity;
435  _averagePrice = averagePrice;
436 
437  OnQuantityChanged(previousAveragePrice, previousQuantity);
438  }
439 
440  /// <summary>
441  /// Update local copy of closing price value.
442  /// </summary>
443  /// <param name="closingPrice">Price of the underlying asset to be used for calculating market price / portfolio value</param>
444  public virtual void UpdateMarketPrice(decimal closingPrice)
445  {
446  _price = closingPrice;
447  }
448 
449  /// <summary>
450  /// Gets the total value of the specified <paramref name="quantity"/> of shares of this security
451  /// in the account currency
452  /// </summary>
453  /// <param name="quantity">The quantity of shares</param>
454  /// <returns>The value of the quantity of shares in the account currency</returns>
455  public virtual ConvertibleCashAmount GetQuantityValue(decimal quantity)
456  {
457  return GetQuantityValue(quantity, _price);
458  }
459 
460  /// <summary>
461  /// Gets the total value of the specified <paramref name="quantity"/> of shares of this security
462  /// in the account currency
463  /// </summary>
464  /// <param name="quantity">The quantity of shares</param>
465  /// <param name="price">The current price</param>
466  /// <returns>The value of the quantity of shares in the account currency</returns>
467  public virtual ConvertibleCashAmount GetQuantityValue(decimal quantity, decimal price)
468  {
469  var amount = price * quantity * _security.SymbolProperties.ContractMultiplier;
470  return new ConvertibleCashAmount(amount, _security.QuoteCurrency);
471  }
472 
473  /// <summary>
474  /// Profit if we closed the holdings right now including the approximate fees in units of the account's currency.
475  /// </summary>
476  /// <remarks>Does not use the transaction model for market fills but should.</remarks>
477  public virtual decimal TotalCloseProfit(bool includeFees = true, decimal? exitPrice = null, decimal? entryPrice = null, decimal? quantity = null)
478  {
479  var quantityToUse = quantity ?? Quantity;
480  if (quantityToUse == 0)
481  {
482  return 0;
483  }
484 
485  // this is in the account currency
486  var marketOrder = new MarketOrder(_security.Symbol, -quantityToUse, _security.LocalTime.ConvertToUtc(_security.Exchange.TimeZone));
487 
488  var feesInAccountCurrency = 0m;
489  if (includeFees)
490  {
491  var orderFee = _security.FeeModel.GetOrderFee(
492  new OrderFeeParameters(_security, marketOrder)).Value;
493  feesInAccountCurrency = _currencyConverter.ConvertToAccountCurrency(orderFee).Amount;
494  }
495 
496  var price = marketOrder.Direction == OrderDirection.Sell ? _security.BidPrice : _security.AskPrice;
497  if (price == 0)
498  {
499  // Bid/Ask prices can both be equal to 0. This usually happens when we request our holdings from
500  // the brokerage, but only the last trade price was provided.
501  price = _security.Price;
502  }
503 
504  var entryValue = GetQuantityValue(quantityToUse, entryPrice ?? AveragePrice).InAccountCurrency;
505  var potentialExitValue = GetQuantityValue(quantityToUse, exitPrice ?? price).InAccountCurrency;
506  return potentialExitValue - entryValue - feesInAccountCurrency;
507  }
508 
509  /// <summary>
510  /// Writes out the properties of this instance to string
511  /// </summary>
512  public override string ToString()
513  {
514  return Messages.SecurityHolding.ToString(this);
515  }
516 
517  /// <summary>
518  /// Event invocator for the <see cref="QuantityChanged"/> event
519  /// </summary>
520  protected virtual void OnQuantityChanged(decimal previousAveragePrice, decimal previousQuantity)
521  {
523  _security, previousAveragePrice, previousQuantity
524  ));
525  }
526  }
527 }