/// <summary>
        /// Retrieves available call and put options for a given ticker.
        /// </summary>
        /// <param name="mdq">The market data query.</param>
        /// <param name="marketData">The requested market data.</param>
        /// <returns>The result of the query.</returns>
        private RefreshStatus GetCallPriceMarketData(MarketDataQuery mdq, out IMarketData marketData)
        {
            marketData = null;
            Fairmat.MarketData.CallPriceMarketData data = new Fairmat.MarketData.CallPriceMarketData();

            List <MEFFHistoricalQuote> options = MEFFAPI.GetOptions(mdq.Ticker, mdq.Date);

            foreach (MEFFHistoricalQuote q in options)
            {
                Console.WriteLine(q.ContractCode + "\t" + q.StrikePrice + "\t" + q.MaturityDate.ToShortDateString() + "\t" + q.SettlPrice);
            }

            var status = OptionQuotesUtility.GetCallPriceMarketData(this, mdq, options.ConvertAll(x => (OptionQuotes.IOptionQuote)x), data);

            if (status.HasErrors)
            {
                return(status);
            }

            marketData = data;
            Console.WriteLine(data);
            return(status);
        }
        /// <summary>
        /// Retrieves available call and put options for a given ticker.
        /// </summary>
        /// <param name="mdq">The market data query.</param>
        /// <param name="marketData">The requested market data.</param>
        /// <returns>A <see cref="RefreshStatus"/> with the status of the result.</returns>
        private RefreshStatus GetCallPriceMarketData(MarketDataQuery mdq, out IMarketData marketData)
        {
            marketData = null;

            //Check if the market data is in cache
            string cachedName = Path.Combine(Path.GetTempPath(), "CallPrices" + mdq.Ticker + mdq.Date.Year + mdq.Date.Month + mdq.Date.Day);
            List <YahooOptionChain> optionChains = null;

            if (System.IO.File.Exists(cachedName))
            {
                try
                {
                    optionChains = (List <YahooOptionChain>)DVPLI.ObjectSerialization.ReadFromFile(cachedName);
                }
                catch
                {
                    //Failed to read from cache
                }
            }

            //if not found in cache try to get from the Yahoo service
            if (optionChains == null)
            {
                //Yahoo returns only last traded options hence, we assume that the only
                //valid dates are Today and Yesterday

                DateTime tMax = DateTime.Today;
                DateTime tMin = tMax.AddDays(-1);
                if (tMax.DayOfWeek == DayOfWeek.Monday)
                {
                    tMin = tMax.AddDays(-3);
                }

                if (mdq.Date.Date < tMin || mdq.Date.Date > tMax)
                {
                    return(new RefreshStatus("Options are not available for the requested period. Set the valuation date to Yesterday"));
                }

                // Request options does not seems to give the option effectively
                // tradaded at a given date but the options that are still being traded.
                optionChains = YahooFinanceAPI.RequestOptions(mdq.Ticker);
                try
                {
                    DVPLI.ObjectSerialization.WriteToFile(cachedName, optionChains);
                }
                catch
                {
                }
            }

            Fairmat.MarketData.CallPriceMarketData data = new Fairmat.MarketData.CallPriceMarketData();


            // Extract a list of YahooOption from the YahooOptionChain List.
            List <YahooOption> options = new List <YahooOption>();

            foreach (YahooOptionChain q in optionChains)
            {
                Console.WriteLine(q.Symbol + " " + q.Expiration);
                foreach (YahooOption o in q.Options)
                {
                    // Loads into YahooOption the needed information.
                    o.Maturity = q.Expiration;
                    options.Add(o);
                }
            }

            // Populate the CallPriceMarketData data structure
            var status = OptionQuotesUtility.GetCallPriceMarketData(this, mdq, options.ConvertAll(x => (IOptionQuote)x), data);

            if (status.HasErrors)
            {
                return(status);
            }

            marketData = data;
            Console.WriteLine(data);
            return(status);
        }
示例#3
0
        /// <summary>
        /// Populates CallPriceMarketData data structure from options
        /// quotes and additional calls to market data.
        /// </summary>
        /// <param name="provider">The underlying market data provider.</param>
        /// <param name="mdq">The underlying query.</param>
        /// <param name="quotes">The options quotes list.</param>
        /// <param name="data">The data structure to be populated.</param>
        /// <returns>The status of the operation.</returns>
        public static RefreshStatus GetCallPriceMarketData(IMarketDataProvider provider, MarketDataQuery mdq, List <IOptionQuote> quotes, Fairmat.MarketData.CallPriceMarketData data)
        {
            // Gets call options.
            var calls = quotes.FindAll(x => x.Type == OptionQuoteType.Call);
            var puts  = quotes.FindAll(x => x.Type == OptionQuoteType.Put);

            // Get maturities and strikes.
            var maturtiesDates = quotes.Select(item => item.Maturity).Distinct().OrderBy(x => x).ToList();
            var strikes        = quotes.Select(item => item.Strike).Distinct().OrderBy(x => x).ToList();

            data.Strike = (Vector)strikes.ToArray();
            //var callMaturtiesDates = calls.Select(item => item.MaturityDate).Distinct().ToList();

            Console.WriteLine("Maturities");
            data.Maturity = new Vector(maturtiesDates.Count);
            for (int z = 0; z < maturtiesDates.Count; z++)
            {
                data.Maturity[z] = RightValueDate.DatesDifferenceCalculator(mdq.Date, maturtiesDates[z]);
            }

            data.CallPrice = new Matrix(data.Maturity.Length, data.Strike.Length);
            var putPrices = new Matrix(data.Maturity.Length, data.Strike.Length);

            // Group maturities, calls, puts  with respect to strikes.
            Dictionary <double, Tuple <List <double>, List <double>, List <double> > > atm = new Dictionary <double, Tuple <List <double>, List <double>, List <double> > >();

            for (int si = 0; si < data.Strike.Length; si++)
            {
                for (int mi = 0; mi < maturtiesDates.Count; mi++)
                {
                    IOptionQuote callQuote = calls.Find(x => x.Strike == data.Strike[si] && x.Maturity == maturtiesDates[mi]);
                    if (callQuote != null)
                    {
                        data.CallPrice[mi, si] = callQuote.Price;
                    }

                    IOptionQuote putQuote = puts.Find(x => x.Strike == data.Strike[si] && x.Maturity == maturtiesDates[mi]);
                    if (putQuote != null)
                    {
                        putPrices[mi, si] = putQuote.Price;
                    }

                    if (callQuote != null && putQuote != null)
                    {
                        Tuple <List <double>, List <double>, List <double> > element = null;

                        if (atm.ContainsKey(data.Strike[si]))
                        {
                            element = atm[data.Strike[si]];
                        }
                        else
                        {
                            element = new Tuple <List <double>, List <double>, List <double> >(new List <double>(), new List <double>(), new List <double>());
                            atm.Add(data.Strike[si], element);
                        }

                        element.Item1.Add(data.Maturity[mi]);
                        element.Item2.Add(callQuote.Price);
                        element.Item3.Add(putQuote.Price);
                    }
                }
            }

            Console.WriteLine("CallPrices");
            Console.WriteLine(data.CallPrice);
            Console.WriteLine("Putprices");
            Console.WriteLine(putPrices);

            // Request the spot price .
            var mdq2 = DVPLI.ObjectSerialization.CloneObject(mdq) as MarketDataQuery;

            mdq2.MarketDataType = typeof(Scalar).ToString();
            IMarketData s0;
            var         s0Result = provider.GetMarketData(mdq2, out s0);

            if (s0Result.HasErrors)
            {
                return(s0Result);
            }

            data.S0 = (s0 as Scalar).Value;

            // Load atm info (get the strike with the higher number of elements).
            int    maxElements = -1;
            double argMax      = -1;

            // Keeps the Strike-Spot distance.
            double spotDistance = double.MaxValue;

            // Find the options which minimize the distance from strike price and spot price.
            foreach (double strike in atm.Keys)
            {
                double distance = Math.Abs(strike - data.S0);
                if (distance < spotDistance)
                {
                    spotDistance = distance;
                    maxElements  = atm[strike].Item1.Count;
                    argMax       = strike;
                }
            }

            if (spotDistance != double.MaxValue)
            {
                data.StrikeATM    = argMax;
                data.MaturityATM  = (Vector)atm[argMax].Item1.ToArray();
                data.CallPriceATM = (Vector)atm[argMax].Item2.ToArray();
                data.PutPriceATM  = (Vector)atm[argMax].Item3.ToArray();
            }
            else
            {
                Console.WriteLine("Cannot find atm information");
            }

            data.Ticker = mdq.Ticker;
            data.Market = mdq.Market;
            data.Date   = mdq.Date;

            return(new RefreshStatus());
        }