double GetDefaultIncrement(BokRateEvent curEvent, DateTime curDate)
        {
            int remainDays = (curEvent.EndDate - curDate).Days;

            if (remainDays < 0)
            {
                return 0.0;
            }

            if (remainDays < 90)
            {
                double y = (double)remainDays / 90;
                double increment = y * curEvent.TargetIncrement * (-1);
                return increment;
            }
            else if (remainDays <= 670)
            {
                return curEvent.TargetIncrement * (-1);
            }
            else
            {
                double daysAfterStart = (365 * 2 + 1) - remainDays;
                Trace.Assert(daysAfterStart <= 60);
                if (daysAfterStart < 0)
                {
                    return 0.0;
                }
                Trace.Assert(daysAfterStart >= 0);
                double y = daysAfterStart / 60;
                double increment = y * curEvent.TargetIncrement * (-1);
                return increment;
            }
        }
        public AdjRateDatum GetIncrement(
            BokRateEvent lastEvent, 
            List<BokRateEvent> events,
            DateTime curDate,
            double weight)
        {
            List<double> increments = new List<double>();
            foreach (BokRateEvent ev in events)
            {
                double curIncrement = GetIncrementEach(lastEvent, ev, curDate);
                increments.Add(curIncrement);
            }

            double totalIncrement = weight * (1.0 + increments.Sum());

            totalIncrement = MathUtil.CapAndFloor(totalIncrement);

            if (totalIncrement < 0.0)
            {
                logger.Warn("BokRate TotalIncrement < 0.0 ({0})", totalIncrement);
                //Trace.Assert(totalIncrement >= 0.0);
                totalIncrement = 0.0;
            }

            return new AdjRateDatum(totalIncrement, 1, 1);
        }
        public void Clear()
        {
            _events.Clear();
            _lastEvent = null;

            _nextAdjustment.Clear();
        }
        double GetDoubleDownFactor(BokRateEvent lastEvent, BokRateEvent curEvent)
        {
            Trace.Assert(lastEvent.UpDown != UpDown.Same);
            Trace.Assert(lastEvent.UpDown != UpDown.Unknown);
            Trace.Assert(curEvent.UpDown != UpDown.Same);
            Trace.Assert(curEvent.UpDown != UpDown.Unknown);

            double factor = 1;
            const double kFactor = 1.3;
            //const double kFactor = 1000;
            double devide = kFactor;
            if (lastEvent.UpDown != curEvent.UpDown)
            {
                devide = kFactor;
            }

            int diff = lastEvent.EventKey - curEvent.EventKey;
            for (int i = 0; i < diff; ++i)
            {
                factor /= devide;
            }
            return factor;
        }
        public AdjRateDatum CalculateAssetWeight_Raw(OperationSet opSet, DateTime targetDate, MarketDataSet data)
        {
            MarketData md = data.GetData(MarketDataSetKey.BokRate);
            DOHLC dohlc = md.GetData(targetDate);

            AdjRateDatum ret = null;

            if (_prevMarketData == null)
            {
                ret = new AdjRateDatum(1, 1, 1);
            }
            else
            {
                double prevValue = _prevMarketData.OHLC.Close;
                double curValue = dohlc.OHLC.Close;

                // changed more than 1 bp
                if (Math.Abs(prevValue - curValue) > 0.01)
                {
                    double increment = curValue / prevValue - 1;
                    // 금리 변동이 있다.
                    BokRateEvent ev = new BokRateEvent();
                    ev.TargetIncrement = increment;
                    ev.StartDate = targetDate;
                    ev.EndDate = targetDate.AddYears(kEventDuration);
                    ev.EventKey = _eventKeyGenerator++;
                    ev.UpDown = increment > 0 ? UpDown.Up : UpDown.Down;

                    _events.Add(ev);
                    _lastEvent = ev;
                }
                ret = GetIncrement(targetDate);
            }
            _prevMarketData = dohlc;

            return ret;
        }
        double GetIncrementEach(
            BokRateEvent lastEvent, 
            BokRateEvent curEvent, 
            DateTime curDate)
        {
            if (curEvent.EndDate < curDate)
            {
                // 기한이 지났다.
                return 0;
            }
            double doubleDownFactor = GetDoubleDownFactor(lastEvent, curEvent);
            double defaultIncrement = GetDefaultIncrement(curEvent, curDate);

            double ret =  defaultIncrement * doubleDownFactor;
            return ret;
        }