Пример #1
0
        public static AssetSize GetAssetWithSmallestReminder(
            this AssetAllocation allocation,
            Money portfolioCost,
            Dictionary <string, Money> prices)
        {
            AssetSize size         = null;
            decimal   bestReminder = decimal.MaxValue;

            foreach (var portion in allocation.Portions)
            {
                var ticker     = portion.Ticker;
                var targetCost = portfolioCost * portion.Portion;

                var targetNumber = Math.Floor(targetCost / prices[ticker]);

                var rest = (targetCost - targetNumber * prices[ticker]).As(Currency.Rubles).Value;

                if (bestReminder > rest)
                {
                    bestReminder = rest;
                    size         = new AssetSize(portion.Ticker, Convert.ToInt32(targetNumber));
                }
            }

            return(size);
        }
Пример #2
0
        public IReadOnlyList <Action> GetActions(
            Portfolio portfolio,
            AssetAllocation allocation,
            IReadOnlyList <AssetPrice> prices)
        {
            var pricesMap = prices.ToDictionary(p => p.Ticker, p => p.Value);

            ValidateThatProcesForAllTickersAreAvailable(portfolio, allocation, pricesMap);

            var targetAssetSizes = CalculateTargetAssetSizes(portfolio, allocation, pricesMap);

            var actions = GetActions(portfolio, targetAssetSizes).OrderBy(a => a.Type).ToArray();

            ValidateActions(portfolio, actions, pricesMap);

            return(actions);
        }
Пример #3
0
        private static Dictionary <string, int> CalculateTargetAssetSizes(Portfolio portfolio, AssetAllocation allocation,
                                                                          Dictionary <string, Money> pricesMap)
        {
            var portfolioCost = portfolio.Cost(pricesMap);

            var targetAssetSizes = new Dictionary <string, int>();

            while (allocation.Portions.Count > 0)
            {
                var assetSize = allocation.GetAssetWithSmallestReminder(portfolioCost, pricesMap);
                allocation = allocation.Remove(assetSize.Ticker);

                targetAssetSizes[assetSize.Ticker] = assetSize.Size;

                portfolioCost = portfolioCost - assetSize.Size * pricesMap[assetSize.Ticker];
            }

            return(targetAssetSizes);
        }
Пример #4
0
        private static void ValidateThatProcesForAllTickersAreAvailable(Portfolio portfolio, AssetAllocation allocation,
                                                                        Dictionary <string, Money> pricesMap)
        {
            foreach (var ticker in portfolio.Assets.Select(a => a.Ticker))
            {
                if (!pricesMap.ContainsKey(ticker))
                {
                    throw new ArgumentException($"There is no price for ticker '{ticker}' in portfolio.");
                }
            }

            foreach (var ticker in allocation.Portions.Select(p => p.Ticker))
            {
                if (!pricesMap.ContainsKey(ticker))
                {
                    throw new ArgumentException($"There is no price for ticker '{ticker}' in asset allocation.");
                }
            }
        }