/// <summary>
        /// Executes the command.
        /// </summary>
        /// <param name="reportParameters">Parameters used to get the data.</param>
        /// <returns></returns>
        public PositionReport Execute(PositionReportParameters reportParameters)
        {
            this.logger.Log(LogType.Trace, this.GetAssemblyName(), "Enter {0}.Execute", this.GetType().Name);

            Guard.IsNotNull(reportParameters, "reportParameters");

            var data = this.BuildData(reportParameters);

            this.logger.Log(LogType.Trace, this.GetAssemblyName(), "Exit {0}.Execute", this.GetType().Name);

            return(data);
        }
        /// <summary>
        /// Gets the report data in cases where the data has not been supplied
        /// </summary>
        /// <param name="reportParameters">The report parameters.</param>
        /// <returns>Report data where possible, or null if not.</returns>
        public PositionReport BuildData(PositionReportParameters reportParameters)
        {
            var user        = this.userIdentity.Username;
            var runDateTime = this.dateTimeService.Now;

            var    date       = runDateTime.Date;
            string fundGroups = reportParameters.FundGroups.Any()
                                     ? string.Join(",", reportParameters.FundGroups.ConvertAll(i => i.Code))
                                     : "ALL";

            var fundGroupIds = reportParameters.FundGroups.Any()
                                   ? reportParameters.FundGroups.Select(g => g.FundGroupId).ToList()
                                   : null;

            var fundsWithDealingCalendars = this.GetRequiredFundsWithDealingCalendars(fundGroupIds, date).ToList();
            var groups = fundsWithDealingCalendars.ConvertAll(f => f.Fund.FundGroup).Distinct();

            // Get current values for funds selected (at the value date specified by its dealing calndar (or null for latest))
            var valuationParams =
                fundsWithDealingCalendars.ConvertAll(
                    f =>
                    new ValuationParameters
            {
                CdbPrtId      = f.Fund.PrtId,
                HedgeType     = f.Fund.HedgeType,
                ValuationType = f.Fund.ValuationType,
                ValueDate     = f.DealingCalendar == null ? null : f.DealingCalendar.DealingDate,         // No dealing calendar = get latest valuation
            });
            var valuations = this.valuationRepository.GetValuationsByCdbPrtIdList(valuationParams);

            // Get core trades for funds selected
            //var tradeBlotterOptions = new CoreBlotterOptions { };
            //this.orderManagementService.GetCoreTrades()

            var forwardContracts = forwardContractRepository.GetForwardContractsByFundIdList(fundsWithDealingCalendars.ConvertAll(f => f.Fund.FundId));

            var r      = new Random();
            var report =
                PositionReportBuilder.Build()
                .WithHeading("Position Report")
                .WithSubHeading(string.Format("Daily Hedge Position Report for {0} funds.", fundGroups))
                .WithSubHeading(string.Format("Run on {0:dd'-'MMM'-'yyyy} at {0:hh:mm:ss} by {1}", runDateTime, user))
                .WithValidationError("This is a message that could be generated and shown at the top of the report! For example:");

            groups.ForEach(
                g =>
            {
                var group = PositionReportGroupBuilder.Build().WithHeading(g.Name);
                report.WithGroup(group);

                (from fundWithDealingCalendar in fundsWithDealingCalendars
                 where fundWithDealingCalendar.Fund.FundGroup.Equals(g)
                 select fundWithDealingCalendar.Fund).ForEach(
                    fnd =>
                {
                    Valuation val       = valuations.SingleOrDefault(v => v.CdbPrtId == fnd.PrtId);
                    ForwardContract fwd = forwardContracts.SingleOrDefault(fw => fw.FundId == fnd.FundId);

                    var randomError = r.Next(1, 100);
                    var row         =
                        PositionReportRowBuilder.Build()
                        .WithFund(fnd)
                        .WithFundValue(val == null ? null : val.FundValue)
                        .WithFundValueDate(val == null ? null : val.ValueDate)
                        .WithHedgeCurrency(fnd.HedgeType == HedgeType.Investment ? fnd.FeedsInto.Ccy : fnd.Ccy)
                        .WithCurrentLevel(GetCurrentLevel(fwd, fnd.HedgeType));

                    // Example error
                    if (randomError < 6)
                    {
                        row.WithHighlight(true).WithMessage("Error " + randomError);
                        report.WithValidationError(string.Format("{0} has {1}", row.Fund.GamFundCode, row.Message));
                    }

                    group.WithRow(row);
                });
            });

            return(report);
        }