public decimal CalculateDailyMTD(DailyPnL current, DailyPnL prior)
        {
            var convertedPriorDaily   = prior.MTDPercentageReturn.Value + 1;
            var convertedCurrentDaily = current.DailyPercentageReturn.HasValue ? current.DailyPercentageReturn.Value + 1 : 1;

            return(Math.Round((convertedPriorDaily * convertedCurrentDaily) - 1, 16));
        }
        public decimal CalculateDailyYTD(DailyPnL current, DailyPnL prior)
        {
            var convertedPriorYTD   = prior.YTDPercentageReturn.Value + 1;
            var convertedCurrentMTD = current.MTDPercentageReturn.HasValue ? current.MTDPercentageReturn.Value + 1 : 1;

            //return (convertedPriorYTD * convertedCurrentMTD) - 1;
            return(Math.Round((convertedPriorYTD * convertedCurrentMTD) - 1, 16));
        }
        public bool Run(PostingEngineEnvironment env)
        {
            env.CallBack?.Invoke($"{Module} Started");

            env.CallBack?.Invoke("Getting Daily Pnl Data");

            var performanceRecords = DailyPnL.GetList(env.ConnectionString);

            env.CallBack?.Invoke($"{Module} Running the calculation");

            var dailyPerformanceResult = new DailyPnlCalculator().CalculateDailyPerformance(performanceRecords);
            var dailyPerformance       = dailyPerformanceResult.GetType().GetProperty("payload")
                                         ?.GetValue(dailyPerformanceResult, null);
            bool insertDailyPnl = UpdateDailyPnl((List <DailyPnL>)dailyPerformance, env.ConnectionString);

            env.CallBack?.Invoke($"{Module} Finished");

            return(true);
        }
        /// <summary>
        /// I already have a populated database, and as a result I should be able to have the system
        /// recalculate when I finish the EOD / SOD process
        /// </summary>
        /// <param name="performanceRecords"></param>
        /// <returns></returns>
        public object CalculateDailyPerformance(List <DailyPnL> performanceRecords)
        {
            var sorted = performanceRecords.OrderBy(x => x.BusinessDate).ThenBy(x => x.RowId).ToList();

            var groupedByPortfolio = sorted.GroupBy(x => x.PortFolio).Select(x => new
            {
                Portfolio  = x.Key,
                YearlyData = x.ToList().GroupBy(y => y.BusinessDate.Year).Select(z => new
                {
                    Year        = z.Key,
                    MonthlyData = z.ToList().GroupBy(w => w.BusinessDate.Month)
                })
            }).ToList();

            //var groupedByYear = sorted.GroupBy(x => x.PerformanceDate.Year).ToList();

            DailyPnL priorData             = null;
            int      monthIndex            = 0;
            int      totalMonthlyRecords   = 0;
            DailyPnL priorDataYearlyPnl    = priorData;
            DailyPnL priorDataQuarterlyPnl = priorData;
            DailyPnL priorDataInceptionPnl = priorData;

            DailyPnL priorDataForQuarter   = priorData;
            DailyPnL priorDataForYear      = priorData;
            DailyPnL priorDataForInception = priorData;

            Dictionary <int, int> quarterCount = new Dictionary <int, int>();

            InitializeQuarterDictionary(quarterCount);

            foreach (var portfolio in groupedByPortfolio)
            {
                foreach (var year in portfolio.YearlyData)
                {
                    foreach (var month in year.MonthlyData)
                    {
                        totalMonthlyRecords = month.Count() - 1;
                        monthIndex          = 0;
                        foreach (var item in month)
                        {
                            if (!item.ExistingRecord)
                            {
                                if (priorData != null)
                                {
                                    item.MTDPercentageReturn = CalculateDailyMTD(item, priorData);
                                    item.MTDPnL = CalculateDailyPnl(item.Day, priorData.MTDPnL);
                                }
                                else
                                {
                                    item.MTDPercentageReturn = item.DailyPercentageReturn;
                                    item.MTDPnL = item.Day;
                                }

                                if (priorDataForYear != null)
                                {
                                    item.YTDPercentageReturn = CalculateDailyYTD(item, priorDataForYear);
                                }
                                else
                                {
                                    item.YTDPercentageReturn = item.MTDPercentageReturn;
                                }

                                if (priorDataForInception != null)
                                {
                                    item.ITDPercentageReturn = CalculateDailyITD(item, priorDataForInception);
                                }
                                else
                                {
                                    item.ITDPercentageReturn = item.MTDPercentageReturn;
                                }

                                if (priorDataForQuarter != null)
                                {
                                    if (CheckForBeginningOfQuarter(item.BusinessDate))
                                    {
                                        item.QTDPercentageReturn = item.MTDPercentageReturn;
                                    }
                                    else
                                    {
                                        if (IfDatesLieInTheSameQuarter(priorDataForQuarter.BusinessDate, item.BusinessDate))
                                        {
                                            item.QTDPercentageReturn = CalculateDailyQTD(item, priorDataForQuarter);
                                        }
                                        else
                                        {
                                            item.QTDPercentageReturn = item.MTDPercentageReturn;
                                        }
                                    }
                                }
                                else
                                {
                                    item.QTDPercentageReturn = item.MTDPercentageReturn;
                                }


                                //Calculations for QTD,YTD,ITD values.

                                if (priorDataQuarterlyPnl != null)
                                {
                                    if (CheckForBeginningOfQuarter(item.BusinessDate))
                                    {
                                        item.QTDPnL = item.MTDPnL;
                                    }
                                    else
                                    {
                                        item.QTDPnL = CalculateDailyPnl(item.Day, priorDataQuarterlyPnl.QTDPnL);
                                    }
                                }
                                else
                                {
                                    item.QTDPnL = item.MTDPnL;
                                }

                                if (priorDataYearlyPnl != null)
                                {
                                    item.YTDPnL = CalculateDailyPnl(item.Day, priorDataYearlyPnl.YTDPnL);
                                }
                                else
                                {
                                    item.YTDPnL = item.MTDPnL;
                                }

                                if (priorDataInceptionPnl != null)
                                {
                                    item.ITDPnL = CalculateDailyPnl(item.Day, priorDataInceptionPnl.ITDPnL);
                                }
                                else
                                {
                                    item.ITDPnL = item.MTDPnL;
                                }
                            }

                            priorData             = item;
                            priorDataQuarterlyPnl = item;
                            priorDataYearlyPnl    = item;
                            priorDataInceptionPnl = item;
                            //We have reached the end of the month. At this point, the calculated value of MTD represents MTD returns for that month.
                            //We will use this value of MTD as reference for QTD,YTD,ITD percentage/returns calculation.
                            if (monthIndex == totalMonthlyRecords)
                            {
                                priorDataForYear      = item;
                                priorDataForQuarter   = item;
                                priorDataForInception = item;
                            }

                            monthIndex++;
                        }

                        priorData = null;
                    }

                    priorDataForYear      = null;
                    priorDataYearlyPnl    = null;
                    priorDataQuarterlyPnl = null;
                    priorDataForQuarter   = null;
                }

                priorDataForInception = null;
                priorDataForQuarter   = null;
                priorDataInceptionPnl = null;
                priorDataQuarterlyPnl = null;
            }

            return(Utils.Wrap(true, sorted, HttpStatusCode.OK, "Performance calculated successfully"));
        }
 public void pnl(int reqId, double dailyPnL, double unrealizedPnL, double realizedPnL)
 {
     DailyPnL.RaiseEvent(this, new DailyPnLEventArgs(reqId, dailyPnL, unrealizedPnL, realizedPnL));
 }