void UpdateEventPoint(
            String spotCode, String futureCode, TradingDirection spotDirection, 
            DateTime dateTimeFrom, PairTradingData tradingData, EventPoint ep)
        {
            if (spotDirection == TradingDirection.Long)
            {
                ep.LongCode = spotCode;
                ep.ShortCode = futureCode;
            }
            else
            {
                ep.LongCode = futureCode;
                ep.ShortCode = spotCode;
            }
            ep.DateTimeFrom = dateTimeFrom;

            if (tradingData != null)
            {
                ep.DateTimeTo = tradingData.MaxDateTime;

                ep.RangeMax = tradingData.MaxPnL;
                ep.RangeMin = tradingData.MinPnL;
            }
            else
            {
                ep.DateTimeTo = new DateTime(2999, 12, 31);
                ep.RangeMax = double.NaN;
                ep.RangeMin = double.NaN;
            }
        }
        public List<EventPoint> GetEventPoints(
            PeriodicMarketDataCollection spot, 
            PeriodicMarketDataCollection future,
            TradingDirection spotDirection)
        {
            List<EventPoint> eventPoints = new List<EventPoint>();

            for (int i = 0; i < spot.Rmds.Count - 1; ++i)
            {
                RawMarketData spotStartRmd = spot.Rmds[i];
                RawMarketData futureStartRmd = future.Rmds[i];

                Trace.Assert(spotStartRmd.LastUpdatedTime == futureStartRmd.LastUpdatedTime);

                if (!RawMarketDataUtil.IsValidBidAskCurPrice(spotStartRmd) ||
                    !RawMarketDataUtil.IsValidBidAskCurPrice(futureStartRmd))
                {
                    EventPoint ep = new EventPoint();
                    UpdateEventPoint(spotStartRmd.Code, futureStartRmd.Code, spotDirection,
                        spotStartRmd.LastUpdatedTime, null, ep);
                    eventPoints.Add(ep);
                }
                else
                {
                    PairTradingData tradingData = new PairTradingData(spotDirection);
                    tradingData.SetEnterPrices(spotStartRmd, futureStartRmd, spotDirection);

                    for (int j = i + 1; j < spot.Rmds.Count; ++j)
                    {
                        RawMarketData spotCurRmd = spot.Rmds[j];
                        RawMarketData futureCurRmd = future.Rmds[j];

                        if (!RawMarketDataUtil.IsValidBidAskCurPrice(spotCurRmd) ||
                            !RawMarketDataUtil.IsValidBidAskCurPrice(futureCurRmd))
                        {
                            continue;
                        }
                        tradingData.UpdateExitNowPnL(spotCurRmd, futureCurRmd, spotDirection);
                    }
                    EventPoint ep = new EventPoint();
                    UpdateEventPoint(spotStartRmd.Code, futureStartRmd.Code, spotDirection,
                        spotStartRmd.LastUpdatedTime, tradingData, ep);
                    eventPoints.Add(ep);
                }
            }
            return eventPoints;
        }