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  // avoid any small values, due to differences in lot size, to return invested true but lean not allowing us to trade sice it will be rounded down to 0
125  // specially useful to crypto assets which take fees from the base or quote currency
126  _invested = Math.Abs(value) >= _security.SymbolProperties.LotSize;
127  _quantity = value;
128  }
129  }
130 
131  /// <summary>
132  /// Symbol identifier of the underlying security.
133  /// </summary>
134  public Symbol Symbol
135  {
136  get
137  {
138  return _security.Symbol;
139  }
140  }
141 
142  /// <summary>
143  /// The security type of the symbol
144  /// </summary>
145  public SecurityType Type
146  {
147  get
148  {
149  return _security.Type;
150  }
151  }
152 
153  /// <summary>
154  /// Leverage of the underlying security.
155  /// </summary>
156  public virtual decimal Leverage
157  {
158  get
159  {
160  return _security.BuyingPowerModel.GetLeverage(_security);
161  }
162  }
163 
164  /// <summary>
165  /// Acquisition cost of the security total holdings in units of the account's currency.
166  /// </summary>
167  public virtual decimal HoldingsCost
168  {
169  get
170  {
171  if (Quantity == 0)
172  {
173  return 0;
174  }
176  }
177  }
178 
179  /// <summary>
180  /// Unlevered Acquisition cost of the security total holdings in units of the account's currency.
181  /// </summary>
182  public virtual decimal UnleveredHoldingsCost
183  {
184  get { return HoldingsCost/Leverage; }
185  }
186 
187  /// <summary>
188  /// Current market price of the security.
189  /// </summary>
190  public virtual decimal Price
191  {
192  get
193  {
194  return _price;
195  }
196  protected set
197  {
198  _price = value;
199  }
200  }
201 
202  /// <summary>
203  /// Absolute holdings cost for current holdings in units of the account's currency.
204  /// </summary>
205  /// <seealso cref="HoldingsCost"/>
206  public virtual decimal AbsoluteHoldingsCost
207  {
208  get
209  {
210  return Math.Abs(HoldingsCost);
211  }
212  }
213 
214  /// <summary>
215  /// Unlevered absolute acquisition cost of the security total holdings in units of the account's currency.
216  /// </summary>
217  public virtual decimal UnleveredAbsoluteHoldingsCost
218  {
219  get
220  {
221  return Math.Abs(UnleveredHoldingsCost);
222  }
223  }
224 
225  /// <summary>
226  /// Market value of our holdings in units of the account's currency.
227  /// </summary>
228  public virtual decimal HoldingsValue
229  {
230  get
231  {
232  if (Quantity == 0)
233  {
234  return 0;
235  }
236 
238  }
239  }
240 
241  /// <summary>
242  /// Absolute of the market value of our holdings in units of the account's currency.
243  /// </summary>
244  /// <seealso cref="HoldingsValue"/>
245  public virtual decimal AbsoluteHoldingsValue
246  {
247  get { return Math.Abs(HoldingsValue); }
248  }
249 
250  /// <summary>
251  /// Boolean flag indicating if we hold any of the security
252  /// </summary>
253  public virtual bool HoldStock => _invested;
254 
255  /// <summary>
256  /// Boolean flag indicating if we hold any of the security
257  /// </summary>
258  /// <remarks>Alias of HoldStock</remarks>
259  /// <seealso cref="HoldStock"/>
260  public virtual bool Invested => _invested;
261 
262  /// <summary>
263  /// The total transaction volume for this security since the algorithm started in units of the account's currency.
264  /// </summary>
265  public virtual decimal TotalSaleVolume
266  {
267  get { return _totalSaleVolume; }
268  }
269 
270  /// <summary>
271  /// Total fees for this company since the algorithm started in units of the account's currency.
272  /// </summary>
273  public virtual decimal TotalFees
274  {
275  get { return _totalFees; }
276  }
277 
278  /// <summary>
279  /// Total dividends for this company since the algorithm started in units of the account's currency.
280  /// </summary>
281  public virtual decimal TotalDividends
282  {
283  get { return _totalDividends; }
284  }
285 
286  /// <summary>
287  /// Boolean flag indicating we have a net positive holding of the security.
288  /// </summary>
289  /// <seealso cref="IsShort"/>
290  public virtual bool IsLong
291  {
292  get
293  {
294  return Quantity > 0;
295  }
296  }
297 
298  /// <summary>
299  /// BBoolean flag indicating we have a net negative holding of the security.
300  /// </summary>
301  /// <seealso cref="IsLong"/>
302  public virtual bool IsShort
303  {
304  get
305  {
306  return Quantity < 0;
307  }
308  }
309 
310  /// <summary>
311  /// Absolute quantity of holdings of this security
312  /// </summary>
313  /// <seealso cref="Quantity"/>
314  public virtual decimal AbsoluteQuantity
315  {
316  get
317  {
318  return Math.Abs(Quantity);
319  }
320  }
321 
322  /// <summary>
323  /// Record of the closing profit from the last trade conducted in units of the account's currency.
324  /// </summary>
325  public virtual decimal LastTradeProfit
326  {
327  get
328  {
329  return _lastTradeProfit;
330  }
331  }
332 
333  /// <summary>
334  /// Calculate the total profit for this security in units of the account's currency.
335  /// </summary>
336  /// <seealso cref="NetProfit"/>
337  public virtual decimal Profit
338  {
339  get { return _profit + _totalDividends; }
340  }
341 
342  /// <summary>
343  /// Return the net for this company measured by the profit less fees in units of the account's currency.
344  /// </summary>
345  /// <seealso cref="Profit"/>
346  /// <seealso cref="TotalFees"/>
347  public virtual decimal NetProfit
348  {
349  get
350  {
351  return Profit - TotalFees;
352  }
353  }
354 
355  /// <summary>
356  /// Gets the unrealized profit as a percentage of holdings cost
357  /// </summary>
358  public virtual decimal UnrealizedProfitPercent
359  {
360  get
361  {
362  if (AbsoluteHoldingsCost == 0) return 0m;
364  }
365  }
366 
367  /// <summary>
368  /// Unrealized profit of this security when absolute quantity held is more than zero in units of the account's currency.
369  /// </summary>
370  public virtual decimal UnrealizedProfit
371  {
372  get { return TotalCloseProfit(); }
373  }
374 
375  /// <summary>
376  /// Adds a fee to the running total of total fees in units of the account's currency.
377  /// </summary>
378  /// <param name="newFee"></param>
379  public void AddNewFee(decimal newFee)
380  {
381  _totalFees += newFee;
382  }
383 
384  /// <summary>
385  /// Adds a profit record to the running total of profit in units of the account's currency.
386  /// </summary>
387  /// <param name="profitLoss">The cash change in portfolio from closing a position</param>
388  public void AddNewProfit(decimal profitLoss)
389  {
390  _profit += profitLoss;
391  }
392 
393  /// <summary>
394  /// Adds a new sale value to the running total trading volume in units of the account's currency.
395  /// </summary>
396  /// <param name="saleValue"></param>
397  public void AddNewSale(decimal saleValue)
398  {
399  _totalSaleVolume += saleValue;
400  }
401 
402  /// <summary>
403  /// Adds a new dividend payment to the running total dividend in units of the account's currency.
404  /// </summary>
405  /// <param name="dividend"></param>
406  public void AddNewDividend(decimal dividend)
407  {
408  _totalDividends += dividend;
409  }
410 
411  /// <summary>
412  /// Set the last trade profit for this security from a Portfolio.ProcessFill call in units of the account's currency.
413  /// </summary>
414  /// <param name="lastTradeProfit">Value of the last trade profit</param>
415  public void SetLastTradeProfit(decimal lastTradeProfit)
416  {
417  _lastTradeProfit = lastTradeProfit;
418  }
419 
420  /// <summary>
421  /// Set the quantity of holdings and their average price after processing a portfolio fill.
422  /// </summary>
423  public virtual void SetHoldings(decimal averagePrice, int quantity)
424  {
425  SetHoldings(averagePrice, (decimal) quantity);
426  }
427 
428  /// <summary>
429  /// Set the quantity of holdings and their average price after processing a portfolio fill.
430  /// </summary>
431  public virtual void SetHoldings(decimal averagePrice, decimal quantity)
432  {
433  var previousQuantity = _quantity;
434  var previousAveragePrice = _averagePrice;
435 
436  Quantity = quantity;
437  _averagePrice = averagePrice;
438 
439  OnQuantityChanged(previousAveragePrice, previousQuantity);
440  }
441 
442  /// <summary>
443  /// Update local copy of closing price value.
444  /// </summary>
445  /// <param name="closingPrice">Price of the underlying asset to be used for calculating market price / portfolio value</param>
446  public virtual void UpdateMarketPrice(decimal closingPrice)
447  {
448  _price = closingPrice;
449  }
450 
451  /// <summary>
452  /// Gets the total value of the specified <paramref name="quantity"/> of shares of this security
453  /// in the account currency
454  /// </summary>
455  /// <param name="quantity">The quantity of shares</param>
456  /// <returns>The value of the quantity of shares in the account currency</returns>
457  public virtual ConvertibleCashAmount GetQuantityValue(decimal quantity)
458  {
459  return GetQuantityValue(quantity, _price);
460  }
461 
462  /// <summary>
463  /// Gets the total value of the specified <paramref name="quantity"/> of shares of this security
464  /// in the account currency
465  /// </summary>
466  /// <param name="quantity">The quantity of shares</param>
467  /// <param name="price">The current price</param>
468  /// <returns>The value of the quantity of shares in the account currency</returns>
469  public virtual ConvertibleCashAmount GetQuantityValue(decimal quantity, decimal price)
470  {
471  var amount = price * quantity * _security.SymbolProperties.ContractMultiplier;
472  return new ConvertibleCashAmount(amount, _security.QuoteCurrency);
473  }
474 
475  /// <summary>
476  /// Profit if we closed the holdings right now including the approximate fees in units of the account's currency.
477  /// </summary>
478  /// <remarks>Does not use the transaction model for market fills but should.</remarks>
479  public virtual decimal TotalCloseProfit(bool includeFees = true, decimal? exitPrice = null, decimal? entryPrice = null, decimal? quantity = null)
480  {
481  var quantityToUse = quantity ?? Quantity;
482  if (quantityToUse == 0)
483  {
484  return 0;
485  }
486 
487  // this is in the account currency
488  var orderFee = Extensions.GetMarketOrderFees(_security, -quantityToUse, _security.LocalTime.ConvertToUtc(_security.Exchange.TimeZone), out var marketOrder);
489 
490  var feesInAccountCurrency = 0m;
491  if (includeFees)
492  {
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 }