/* * 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.Linq; using Newtonsoft.Json; using QuantConnect.Logging; using QuantConnect.Securities; using System.Collections.Generic; namespace QuantConnect.Securities.Positions { /// /// Snapshot of an algorithms portfolio state /// public class PortfolioState { /// /// Utc time this portfolio snapshot was taken /// public DateTime Time { get; set; } /// /// The current total portfolio value /// public decimal TotalPortfolioValue { get; set; } /// /// The margin used /// public decimal TotalMarginUsed { get; set; } /// /// The different positions groups /// [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public List PositionGroups { get; set; } /// /// Gets the cash book that keeps track of all currency holdings (only settled cash) /// [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public Dictionary CashBook { get; set; } /// /// Gets the cash book that keeps track of all currency holdings (only unsettled cash) /// [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] public Dictionary UnsettledCashBook { get; set; } /// /// Helper method to create the portfolio state snapshot /// public static PortfolioState Create(SecurityPortfolioManager portfolioManager, DateTime utcNow, decimal currentPortfolioValue) { try { var totalMarginUsed = 0m; var positionGroups = new List(portfolioManager.Positions.Groups.Count); foreach (var group in portfolioManager.Positions.Groups) { var buyingPowerForPositionGroup = group.BuyingPowerModel.GetReservedBuyingPowerForPositionGroup(portfolioManager, group); var positionGroupState = new PositionGroupState { MarginUsed = buyingPowerForPositionGroup, Positions = group.Positions.ToList() }; if (currentPortfolioValue != 0) { positionGroupState.PortfolioValuePercentage = (buyingPowerForPositionGroup / currentPortfolioValue).RoundToSignificantDigits(4); } positionGroups.Add(positionGroupState); totalMarginUsed += buyingPowerForPositionGroup; } var result = new PortfolioState { Time = utcNow, TotalPortfolioValue = currentPortfolioValue, TotalMarginUsed = totalMarginUsed, CashBook = portfolioManager.CashBook.Where(pair => pair.Value.Amount != 0).ToDictionary(pair => pair.Key, pair => pair.Value) }; var unsettledCashBook = portfolioManager.UnsettledCashBook .Where(pair => pair.Value.Amount != 0) .ToDictionary(pair => pair.Key, pair => pair.Value); if (positionGroups.Count > 0) { result.PositionGroups = positionGroups; } if (unsettledCashBook.Count > 0) { result.UnsettledCashBook = unsettledCashBook; } return result; } catch (Exception e) { Log.Error(e); return null; } } } /// /// Snapshot of a position group state /// public class PositionGroupState { /// /// Name of this position group /// [JsonIgnore] public string Name { get; set; } /// /// Currently margin used /// public decimal MarginUsed { get; set; } /// /// The margin used by this position in relation to the total portfolio value /// public decimal PortfolioValuePercentage { get; set; } /// /// The positions which compose this group /// public List Positions { get; set; } } }