/*
* 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;
}
}
}