Lean  $LEAN_TAG$
PositionExtensions.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 System.Collections.Generic;
18 
20 {
21  /// <summary>
22  /// Provides extension methods for <see cref="IPosition"/>
23  /// </summary>
24  public static class PositionExtensions
25  {
26  /// <summary>
27  /// Deducts the specified <paramref name="quantityToDeduct"/> from the specified <paramref name="position"/>
28  /// </summary>
29  /// <param name="position">The source position</param>
30  /// <param name="quantityToDeduct">The quantity to deduct</param>
31  /// <returns>A new position with the same properties but quantity reduced by the specified amount</returns>
32  public static IPosition Deduct(this IPosition position, decimal quantityToDeduct)
33  {
34  var newQuantity = position.Quantity - quantityToDeduct;
35  return new Position(position.Symbol, newQuantity, position.UnitQuantity);
36  }
37 
38  /// <summary>
39  /// Combines the provided positions into a single position with the quantities added and the minimum unit quantity.
40  /// </summary>
41  /// <param name="position">The position</param>
42  /// <param name="other">The other position to add</param>
43  /// <returns>The combined position</returns>
44  public static IPosition Combine(this IPosition position, IPosition other)
45  {
46  if (!position.Symbol.Equals(other.Symbol))
47  {
48  throw new ArgumentException($"Position symbols must match in order to combine quantities.");
49  }
50 
51  return new Position(position.Symbol,
52  position.Quantity + other.Quantity,
53  Math.Min(position.UnitQuantity, other.UnitQuantity)
54  );
55  }
56 
57  /// <summary>
58  /// Consolidates the provided <paramref name="positions"/> into a dictionary
59  /// </summary>
60  /// <param name="positions">The positions to be consolidated</param>
61  /// <returns>A dictionary containing the consolidated positions</returns>
62  public static Dictionary<Symbol, IPosition> Consolidate(this IEnumerable<IPosition> positions)
63  {
64  var consolidated = new Dictionary<Symbol, IPosition>();
65  foreach (var position in positions)
66  {
67  IPosition existing;
68  if (consolidated.TryGetValue(position.Symbol, out existing))
69  {
70  // if it already exists then combine it with the existing
71  consolidated[position.Symbol] = existing.Combine(position);
72  }
73  else
74  {
75  consolidated[position.Symbol] = position;
76  }
77  }
78 
79  return consolidated;
80  }
81 
82  /// <summary>
83  /// Creates a new <see cref="IPosition"/> with quantity equal to <paramref name="numberOfLots"/> times its unit quantity
84  /// </summary>
85  /// <param name="position">The position</param>
86  /// <param name="numberOfLots">The number of lots for the new position</param>
87  /// <returns>A new position with the specified number of lots</returns>
88  public static IPosition WithLots(this IPosition position, decimal numberOfLots)
89  {
90  var sign = position.Quantity < 0 ? -1 : +1;
91  return new Position(position.Symbol, numberOfLots * position.UnitQuantity * sign, position.UnitQuantity);
92  }
93 
94  /// <summary>
95  /// Gets the quantity a group would have if the given position were part of it.
96  /// </summary>
97  /// <param name="position">The position</param>
98  /// <returns>The group quantity</returns>
99  public static decimal GetGroupQuantity(this IPosition position)
100  {
101  return position.Quantity / position.UnitQuantity;
102  }
103  }
104 }