/// <summary>
        /// Projecting for per time point.
        /// </summary>
        public void ProjectPerTimePoint(int timePoint, StateIndependentProjectionResult ecoResult)
        {
            // Calculating for current time
            CalculatePortFolioWideReserveForCurrentTimePoint(ecoResult, timePoint);
            CalculateControlsForCurrentTimePoint(ecoResult, timePoint);

            // Project shaped to next time point
            ProjectShapesNextTimePoint(ecoResult, timePoint + 1);
        }
        /// <summary>
        /// Projecting for per economic scenarios.
        /// </summary>
        public void ProjectPerEconomicScenario(StateIndependentProjectionResult ecoResult)
        {
            Initialize(ecoResult);

            for (var i = 0; i < NumberOfProjectionTimes - 1; i++)
            {
                ProjectPerTimePoint(i, ecoResult);
            }
        }
        /// <summary>
        /// Initializing StateIndependentProjectionResult for time zero.
        /// </summary>
        public void Initialize(StateIndependentProjectionResult ecoResult)
        {
            // Equity
            ecoResult.EquityResults.Equity[0] = Math.Pow(10, 7);

            // Portfolio quantities
            foreach (var portfolio in ecoResult.PortfolioResults)
            {
                portfolio.Value.AssetProcess[0]           = Math.Pow(10, 8);
                portfolio.Value.ProjectedBonusCashFlow[0] = 0.0;
                portfolio.Value.QProcess[0] = 0.0;
            }
        }
        /// <summary>
        /// Projecting for all economic scenarios.
        /// </summary>
        public Balance Project()
        {
            for (var i = 0; i < NumberOfEconomicScenarios; i++)
            {
                var ecoResult = new StateIndependentProjectionResult(
                    Input.Policies.Keys,
                    NumberOfProjectionTimes,
                    EcoScenarioGenerator.SimulateMarket());

                ProjectPerEconomicScenario(ecoResult);

                ProjectionResult.Add(ecoResult);
            }

            return(CalculateBalance());
        }
        /// <summary>
        /// Calculating reserve by discounting cash flow with relevant zero coupon bond prices.
        /// </summary>
        public void CalculatePortFolioWideReserveForCurrentTimePoint(StateIndependentProjectionResult ecoResult,
                                                                     int timePoint)
        {
            foreach (var(portfolio, value) in ecoResult.PortfolioResults)
            {
                value.PortfolioWideTechnicalReserve[timePoint] = Input.PortfolioWideOriginalTechReserves[portfolio][TimePointToIndex(timePoint)]
                                                                 + value.QProcess[timePoint] * Input.PortfolioWideBonusTechReserves[portfolio][TimePointToIndex(timePoint)];

                value.PortfolioWideMarketReserve[timePoint] =
                    ReserveCalculator(
                        timePoint,
                        ecoResult.EconomicScenario[Assets.ShortRate][TimePointToIndex(timePoint)],
                        Input.MarketOriginalCashFlows[portfolio]
                        .Zip(Input.MarketBonusCashFlows[portfolio], (x, y) => x + value.QProcess[timePoint] * y).ToArray());
            }
        }
        /// <summary>
        /// Projecting shapes to next time point.
        /// </summary>
        public void ProjectShapesNextTimePoint(StateIndependentProjectionResult ecoResult, int timePoint)
        {
            var shortRateToLastTimePoint     = ecoResult.EconomicScenario[Assets.ShortRate][TimePointToIndex(timePoint - 1)];
            var lastTimePointRiskyAssetPrice = ecoResult.EconomicScenario[Assets.RiskyAsset][TimePointToIndex(timePoint - 1)];
            var riskyAssetPriceChange        =
                ecoResult.EconomicScenario[Assets.RiskyAsset][TimePointToIndex(timePoint)]
                - lastTimePointRiskyAssetPrice;

            var transactionSum = 0.0;

            // Portfolio quantities
            foreach (var(portfolio, value) in ecoResult.PortfolioResults)
            {
                // Projecting Q-process
                value.QProcess[timePoint] = value.QProcess[timePoint - 1]
                                            + (value.DividendProcess[Index.Zero][timePoint - 1]
                                               + value.DividendProcess[Index.One][timePoint - 1] * value.QProcess[timePoint - 1]) * ProjectionStepSize;

                value.ProjectedBonusCashFlow[timePoint] = value.ProjectedBonusCashFlow[timePoint - 1]
                                                          + (value.QProcess[timePoint] - value.QProcess[timePoint - 1]) / 2
                                                          * (Input.MarketBonusCashFlows[portfolio][TimePointToIndex(timePoint)]
                                                             - Input.MarketBonusCashFlows[portfolio][TimePointToIndex(timePoint - 1)]);

                value.AssetProcess[timePoint] = value.AssetProcess[timePoint - 1]
                                                + shortRateToLastTimePoint * (value.AssetProcess[timePoint - 1]
                                                                              - value.ShareInRiskyStockAssetProcess[timePoint - 1] * lastTimePointRiskyAssetPrice) * ProjectionStepSize
                                                + value.ShareInRiskyStockAssetProcess[timePoint - 1] * riskyAssetPriceChange
                                                - (Input.MarketOriginalCashFlows[portfolio][TimePointToIndex(timePoint)]
                                                   - Input.MarketOriginalCashFlows[portfolio][TimePointToIndex(timePoint - 1)])
                                                - (value.ProjectedBonusCashFlow[timePoint] - value.ProjectedBonusCashFlow[timePoint - 1])
                                                - value.TransactionProcess[Index.Zero][timePoint - 1] * ProjectionStepSize
                                                - value.TransactionProcess[Index.One][timePoint - 1];

                transactionSum += value.TransactionProcess[Index.Zero][timePoint - 1] * ProjectionStepSize
                                  + value.TransactionProcess[Index.One][timePoint - 1];
            }

            // Projecting E-process
            var lastTimeEquity    = ecoResult.EquityResults.Equity[timePoint - 1];
            var shareInRiskyAsset = ecoResult.EquityResults.ShareInRiskyAssetEquity[timePoint - 1];

            ecoResult.EquityResults.Equity[timePoint] = lastTimeEquity
                                                        + shortRateToLastTimePoint * (lastTimeEquity
                                                                                      - shareInRiskyAsset * lastTimePointRiskyAssetPrice) * ProjectionStepSize
                                                        + shareInRiskyAsset * riskyAssetPriceChange + transactionSum;
        }
        /// <summary>
        /// Calculate controls for current time point.
        /// </summary>
        private void CalculateControlsForCurrentTimePoint(StateIndependentProjectionResult ecoResult, int timePoint)
        {
            //TODO OLIVER
            foreach (var portfolio in ecoResult.PortfolioResults)
            {
                var x = 0.0;
                if (timePoint % 12 == 0)
                {
                    if (portfolio.Value.AssetProcess[timePoint] - portfolio.Value.PortfolioWideTechnicalReserve[timePoint] > 0)
                    {
                        x = 0.003 * (portfolio.Value.AssetProcess[timePoint] - portfolio.Value.PortfolioWideTechnicalReserve[timePoint]);
                    }
                    else
                    {
                        x = -(portfolio.Value.AssetProcess[timePoint] - portfolio.Value.PortfolioWideTechnicalReserve[timePoint]);
                    }
                }
                else
                {
                    x = 0;
                }

                var h1            = new double();                                                              //Use "Tax- and expense-modified risk-minimization for insurance payment processes" p.24 with gamma=delta=0
                var rt            = ecoResult.EconomicScenario[Assets.ShortRate][TimePointToIndex(timePoint)]; //todo - unsure if this is the right timePoint conversion here.
                var timePointYear = ProjectionIndexToTimeInYear(timePoint);
                var Y             = 0.0;
                for (var t = timePoint; t <= ProjectionTimeInYearToIndex(ProjectionEndTime); t++)
                {
                    Y = (Input.MarketOriginalCashFlows[portfolio.Key][t] + portfolio.Value.QProcess[timePoint] * Input.MarketBonusCashFlows[portfolio.Key][t])
                        - (Input.MarketOriginalCashFlows[portfolio.Key][timePoint] + portfolio.Value.QProcess[timePoint] * Input.MarketBonusCashFlows[portfolio.Key][timePoint]);

                    h1 = h1 + EcoScenarioGenerator.ZeroCouponBondPriceDerivatives(rt, timePointYear, ProjectionIndexToTimeInYear(t))
                         / EcoScenarioGenerator.ZeroCouponBondPriceDerivatives(rt, timePointYear, ProjectionEndTime)
                         * Y
                         * ProjectionStepSize;
                }

                portfolio.Value.TransactionProcess[Index.Zero][timePoint] = 0.0;
                portfolio.Value.TransactionProcess[Index.One][timePoint]  = x; //take 0.3% of "surplus" if positive, otherwise, transfer so surplus is non-negative
                portfolio.Value.DividendProcess[Index.Zero][timePoint]    = 0.01;
                portfolio.Value.DividendProcess[Index.One][timePoint]     = 0.01;
                portfolio.Value.ShareInRiskyStockAssetProcess[timePoint]  = h1;
            }
            ecoResult.EquityResults.ShareInRiskyAssetEquity[timePoint] = 0.0;
        }