/*
* 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.Linq;
using System.Collections;
using System.Collections.Generic;
using System;
using QuantConnect.Securities.Option;
namespace QuantConnect.Securities.Positions
{
///
/// Provides a default implementation of
///
public class PositionGroup : IPositionGroup
{
///
/// Gets the number of positions in the group
///
public int Count => _positions.Count;
///
/// Gets the key identifying this group
///
public PositionGroupKey Key { get; }
///
/// Gets the whole number of units in this position group
///
public decimal Quantity { get; }
///
/// Gets the positions in this group
///
public IEnumerable Positions => _positions.Values;
///
/// Gets the buying power model defining how margin works in this group
///
public IPositionGroupBuyingPowerModel BuyingPowerModel => Key.BuyingPowerModel;
private readonly Dictionary _positions;
///
/// Initializes a new instance of the class
///
/// The buying power model to use for this group
/// The group quantity, which must be the ratio of quantity to unit quantity of each position
/// The positions comprising this group
/// Thrown when the quantity is not the ratio of quantity to unit quantity of each position
public PositionGroup(IPositionGroupBuyingPowerModel buyingPowerModel, decimal quantity, params IPosition[] positions)
: this(new PositionGroupKey(buyingPowerModel, positions), quantity, positions.ToDictionary(p => p.Symbol))
{
}
///
/// Initializes a new instance of the class
///
/// The deterministic key for this group
/// The group quantity, which must be the ratio of quantity to unit quantity of each position
/// The positions comprising this group
/// Thrown when the quantity is not the ratio of quantity to unit quantity of each position
public PositionGroup(PositionGroupKey key, decimal quantity, params IPosition[] positions)
: this(key, quantity, positions.ToDictionary(p => p.Symbol))
{
}
///
/// Initializes a new instance of the class
///
/// The deterministic key for this group
/// The group quantity, which must be the ratio of quantity to unit quantity of each position
/// The positions comprising this group
/// Thrown when the quantity is not the ratio of quantity to unit quantity of each position
public PositionGroup(PositionGroupKey key, decimal quantity, Dictionary positions)
{
Key = key;
Quantity = quantity;
_positions = positions;
#if DEBUG
if (positions.Any(kvp => Math.Abs(kvp.Value.Quantity / kvp.Value.UnitQuantity) != Math.Abs(Quantity)))
{
throw new ArgumentException(Messages.PositionGroup.InvalidQuantity(Quantity, positions.Values));
}
#endif
}
///
/// Attempts to retrieve the position with the specified symbol
///
/// The symbol
/// The position, if found
/// True if the position was found, otherwise false
public bool TryGetPosition(Symbol symbol, out IPosition position)
{
return _positions.TryGetValue(symbol, out position);
}
/// Returns a string that represents the current object.
/// A string that represents the current object.
public override string ToString()
{
return $"{Key}: {Quantity}";
}
/// Returns an enumerator that iterates through the collection.
/// An enumerator that can be used to iterate through the collection.
public IEnumerator GetEnumerator()
{
return Positions.GetEnumerator();
}
/// Returns an enumerator that iterates through a collection.
/// An object that can be used to iterate through the collection.
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
///
/// Instantiates a default empty position group instance
///
/// The buying power model to use for this group
public static PositionGroup Empty(IPositionGroupBuyingPowerModel buyingPowerModel)
{
return new PositionGroup(new PositionGroupKey(buyingPowerModel, new List()), 0m);
}
}
}