/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; namespace QuantConnect.Securities.Positions { /// /// Provides extension methods for /// public static class PositionExtensions { /// /// Deducts the specified from the specified /// /// The source position /// The quantity to deduct /// A new position with the same properties but quantity reduced by the specified amount public static IPosition Deduct(this IPosition position, decimal quantityToDeduct) { var newQuantity = position.Quantity - quantityToDeduct; return new Position(position.Symbol, newQuantity, position.UnitQuantity); } /// /// Combines the provided positions into a single position with the quantities added and the minimum unit quantity. /// /// The position /// The other position to add /// The combined position public static IPosition Combine(this IPosition position, IPosition other) { if (!position.Symbol.Equals(other.Symbol)) { throw new ArgumentException($"Position symbols must match in order to combine quantities."); } return new Position(position.Symbol, position.Quantity + other.Quantity, Math.Min(position.UnitQuantity, other.UnitQuantity) ); } /// /// Consolidates the provided into a dictionary /// /// The positions to be consolidated /// A dictionary containing the consolidated positions public static Dictionary Consolidate(this IEnumerable positions) { var consolidated = new Dictionary(); foreach (var position in positions) { IPosition existing; if (consolidated.TryGetValue(position.Symbol, out existing)) { // if it already exists then combine it with the existing consolidated[position.Symbol] = existing.Combine(position); } else { consolidated[position.Symbol] = position; } } return consolidated; } /// /// Creates a new with quantity equal to times its unit quantity /// /// The position /// The number of lots for the new position /// A new position with the specified number of lots public static IPosition WithLots(this IPosition position, decimal numberOfLots) { var sign = position.Quantity < 0 ? -1 : +1; return new Position(position.Symbol, numberOfLots * position.UnitQuantity * sign, position.UnitQuantity); } /// /// Gets the quantity a group would have if the given position were part of it. /// /// The position /// The group quantity public static decimal GetGroupQuantity(this IPosition position) { return position.Quantity / position.UnitQuantity; } } }