/// <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); }
/// <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()); }