public override Report Run(Dictionary <string, Dictionary <DateTime, ITradingData> > portfolioDataset,
                            List <DateTime> tradingCalendar,
                            BacktestingProperty property,
                            Dictionary <string, PortfolioSubject> portfolio,
                            Period period,
                            bool isBenchmark = false)
 {
     _simulator = new Simulator();
     return(_simulator.Run(this, portfolioDataset, tradingCalendar, property, portfolio, period, isBenchmark));
 }
        public Report Run(StrategyBase strategy,
                          Dictionary <string, Dictionary <DateTime, ITradingData> > portfolioDataset,
                          List <DateTime> tradingCalendar,
                          BacktestingProperty property,
                          Dictionary <string, PortfolioSubject> portfolio,
                          Period period,
                          bool isBenchmark = false)
        {
            _strategy         = strategy;
            _isBenchmark      = isBenchmark;
            _report           = new Report(_strategy.StrategyType);
            _portfolioDataset = portfolioDataset;
            _tradingCalendar  = tradingCalendar;
            _portfolio        = portfolio;
            Property          = property;

            _balance = property.Capital;

            _highestTotalBalance = property.Capital;

            foreach (var assetCode in _portfolioDataset.Keys)
            {
                var initialBalance = Property.Capital * _portfolio[assetCode].Ratio;

                _holdStocks.Add(assetCode, new HoldStock
                {
                    InitialBalance = initialBalance
                });

                _report.Transactions.Add(assetCode, new Dictionary <DateTime, List <Transaction> >());

                // 에셋별로 실제거래한 날짜데이터를 갖는다(트레이딩 달력이랑 다름)
                var tradingDate = portfolioDataset[assetCode].Keys.ToList();
                _tradingDates.Add(assetCode, tradingDate);
                _tradingIndex.Add(assetCode, 0);
                _recordDetails.Add(assetCode, new List <RecordDetail>());
            }

            foreach (var date in tradingCalendar)
            {
                _currentDate          = date; // 트레이딩 달력기준 날짜
                _totalBalanceSnapshot = _report.Records.Count > 0 ? _report.Records.Last().TotalBalance : _balance;

                var recordDetails = new List <RecordDetail>();
                foreach (var assetCode in _portfolioDataset.Keys)
                {
                    var subjectDataset = _portfolioDataset[assetCode];
                    if (subjectDataset.ContainsKey(date))
                    {
                        _strategy.OnAfterOpen(assetCode);

                        var recordDetail = CreateRecordDetail(assetCode);
                        _recordDetails[assetCode].Add(recordDetail);

                        recordDetails.Add(recordDetail);
                        _tradingIndex[assetCode]++;
                    }
                    else
                    {
                        // var prevRecord = _report.Records.OrderByDescending(x => x.Date).Take(1).FirstOrDefault();
                        var prevRecordDetail = _recordDetails[assetCode].OrderByDescending(x => x.Date).Take(1).FirstOrDefault();
                        if (prevRecordDetail != null)
                        {
                            var recordDetail = new RecordDetail()
                            {
                                Date             = _currentDate,
                                AssetCode        = assetCode,
                                RatingBalance    = prevRecordDetail.RatingBalance,
                                Return           = 0,
                                ReturnRatio      = 0,
                                CumulativeReturn = prevRecordDetail.CumulativeReturn
                            };
                            _recordDetails[assetCode].Add(recordDetail);
                            recordDetails.Add(recordDetail);
                        }
                    }
                }

                var record = CreateRecord(date, recordDetails);
                _report.Records.Add(record);

                if (IsFirstTradingDateOfYear(_currentDate.Year))
                {
                    _balanceOfYears.Add(_currentDate.Year, new BalanceOfPeriod {
                        FirstDateBalance = _report.Records.Last().TotalBalance
                    });
                }
                else if (IsLastTradingDateOfYear(_currentDate.Year))
                {
                    _balanceOfYears[_currentDate.Year].LastDateBalance = _report.Records.Last().TotalBalance;
                }

                if (IsFirstTradingDateOfMonth(_currentDate.Year, _currentDate.Month))
                {
                    _balanceOfMonths.Add(_currentDate.ToString("yyyy-MM"), new BalanceOfPeriod {
                        FirstDateBalance = _report.Records.Last().TotalBalance
                    });
                }
                else if (IsLastTradingDateOfMonth(_currentDate.Year, _currentDate.Month))
                {
                    _balanceOfMonths[_currentDate.ToString("yyyy-MM")].LastDateBalance = _report.Records.Last().TotalBalance;
                }
            }

            // 통계생성
            string relationalKey  = Guid.NewGuid().ToString();
            var    summaryDetails = CreateSummaryDetails(relationalKey);

            _report.Summary        = CreateSummary(summaryDetails, relationalKey);
            _report.AnnualReturns  = CreateAnnualReturns();
            _report.MonthlyReturns = CreateMonthlyReturns();

            return(_report);
        }
 public abstract Report Run(Dictionary <string, Dictionary <DateTime, ITradingData> > portfolioDataset,
                            List <DateTime> tradingCalendar,
                            BacktestingProperty property,
                            Dictionary <string, PortfolioSubject> portfolio,
                            Period period,
                            bool isBenchmark = false);