private Frame <string, string> CreateFrame(SymbologySearchResponse response) { List <KeyValuePair <string, Series <string, string> > > list = new List <KeyValuePair <string, Series <string, string> > >(); SeriesBuilder <string, string> sb; foreach (var symbol in response.mappedSymbols) { string ric = symbol.symbol; sb = new SeriesBuilder <string, string>(); FieldInfo[] fields = typeof(MappedSymbol).GetFields(); string temp = ""; foreach (var field in fields) { temp = ""; if (field.FieldType == typeof(List <string>)) { List <string> tmpList = (List <string>)field.GetValue(symbol); if (tmpList != null) { temp = string.Join(",", tmpList); } } else if (field.FieldType == typeof(BestMatch)) { if (symbol.bestMatch != null) { // sb = new SeriesBuilder<string, string>(); FieldInfo[] bestMatchFields = typeof(BestMatch).GetFields(); foreach (var bestMatchField in bestMatchFields) { var tmp = bestMatchField.GetValue(symbol.bestMatch)?.ToString(); if (!string.IsNullOrEmpty(tmp)) { sb.Add("BestMatch." + bestMatchField.Name, tmp); } } continue; } } else { temp = field.GetValue(symbol)?.ToString(); } if (!string.IsNullOrEmpty(temp) && field.Name != "symbol") { sb.Add(field.Name, temp); } } list.Add(KeyValue.Create(ric, sb.Series)); } return(Frame.FromRows(list)); }
public void GenDeedle() { var rows = Enumerable.Range(0, 100).Select(i => { var sb = new SeriesBuilder <string>(); sb.Add("Index", i); sb.Add("Sin", Math.Sin(i / 100.0)); sb.Add("Cos", Math.Cos(i / 100.0)); return(KeyValue.Create(i, sb.Series)); }); }
public Frame <int, string> CreateTermDataFrame(Frame <int, string> frame, string termsColumn, string classifierColumnName) { var stopWords = _fileManager.ReadFromFile(_appSettings.StopWordsFilePath) .Distinct() .Select(x => x.ToLower()) .ToList(); var termsByRows = frame.GetColumn <string>(termsColumn).GetAllValues().Select((row, index) => { var seriesBuilder = new SeriesBuilder <string, int>(); var rowWords = Regex.Matches(row.Value, "[a-zA-Z]+('(s|d|t|ve|m))?") .Cast <Match>() .Where(word => !stopWords.Contains(word.Value.ToLower())) .Select(word => word.Value.ToLower()) .Distinct(); foreach (var word in rowWords) { seriesBuilder.Add(word, 1); } return(KeyValue.Create(index, seriesBuilder.Series)); }); var termDataFrame = Frame.FromRows(termsByRows).FillMissing(0); termDataFrame.AddColumn(classifierColumnName, frame.GetColumn <int>(classifierColumnName)); termDataFrame.SaveCsv(_appSettings.TermsVectorFilePath); return(termDataFrame); }
private Frame <int, string> CreateWordFrame(Series <int, string> rows) { var wordsByRows = rows.GetAllValues() .Select((x, i) => { var sb = new SeriesBuilder <string, int>(); ISet <string> words = new HashSet <string>( Regex.Matches(x.Value, "[a-zA-Z]+('(s|d|t|ve|m))?") .Cast <Match>() .Select(y => y.Value.ToLower()) .ToArray() ); // Encode words appeared in each row with 1 foreach (string w in words) { sb.Add(w, 1); } return(KeyValue.Create(i, sb.Series)); }); // Create a data frame from the rows we just created // And encode missing values with 0 var wordFrame = Frame.FromRows(wordsByRows) .FillMissing(0); return(wordFrame); }
private Frame <int, string> CreateFrame(DataResponse response) { if (response != null) { var rows = Enumerable.Range(0, response.data.Count).Select(i => { // Build each row using series builder & return // KeyValue representing row key with row data var sb = new SeriesBuilder <string>(); for (int j = 0; j < response.headers.First().Count(); j++) { string displayName; if (string.IsNullOrEmpty(response.headers.First()[j].displayName)) { displayName = "None"; } else { displayName = response.headers.First()[j].displayName; } sb.Add(displayName, response.data[i][j].Value); } return(KeyValue.Create(i, sb.Series)); }); return(Frame.FromRows(rows)); } else { return(Frame.CreateEmpty <int, string>()); } }
private Frame <string, string> CreateBestMatchFrame(SymbologySearchResponse response) { List <KeyValuePair <string, Series <string, string> > > list = new List <KeyValuePair <string, Series <string, string> > >(); foreach (var symbol in response.mappedSymbols) { string ric = symbol.symbol; SeriesBuilder <string, string> sb; if (symbol.bestMatch != null) { sb = new SeriesBuilder <string, string>(); FieldInfo[] fields = typeof(BestMatch).GetFields(); foreach (var field in fields) { var tmp = field.GetValue(symbol.bestMatch)?.ToString(); if (!string.IsNullOrEmpty(tmp)) { sb.Add(field.Name, field.GetValue(symbol.bestMatch).ToString()); } } // sb.Series.Print(); list.Add(KeyValue.Create(ric, sb.Series)); } } return(Frame.FromRows(list)); }
/// <summary> /// For a frame of type Frame<TRow,TCol> mutate its rows of type TVal and create a new column with the results /// </summary> /// <typeparam name="TRow">Row Type</typeparam> /// <typeparam name="TVal">Value Type</typeparam> /// <typeparam name="TCol">Column Type</typeparam> /// <param name="myFrame"></param> /// <param name="mutatorMethod">delegate for transformation</param> /// <returns>Series<K, V></returns> public static Series <TRow, TVal> Mutate <TRow, TVal, TCol>(this Frame <TRow, TCol> myFrame, Func <TVal[], TVal> mutatorMethod) { SeriesBuilder <TRow, TVal> result = new SeriesBuilder <TRow, TVal>(); foreach (TRow key in myFrame.Rows.Keys) { TVal colResult = mutatorMethod(myFrame.Rows[key].GetValues <TVal>().ToArray()); result.Add(key, colResult); } return(result.ToSeries()); }
public void Add(RegularTimeSeriesRawData item) { var dimensions = new string[_dimensions.Length]; var attributes = new object[_attributes.Length]; foreach (var dim in item.Dimensions) { var dimIndex = _dimensionIdsMap[dim.DimensionId]; dimensions[dimIndex] = dim.Key; attributes[dimIndex] = dim.Name; _dimensionKeyMaps[dimIndex][dim.Name] = dim.Key; } if (item.TimeSeriesAttributes != null) { foreach (var attr in item.TimeSeriesAttributes) { var attrIndex = _attributeIds[attr.Key]; attributes[attrIndex] = attr.Value; } } var frequency = item.Frequency.ToFrequency(); var rangeTuple = Tuple.Create(item.StartDate, item.EndDate, frequency); IReadOnlyList <DateTime> timeRange; if (!_timeRangeCache.TryGetValue(rangeTuple, out timeRange)) { timeRange = TimeFormat.InvariantTimeFormat.ExpandRangeSelection(item.StartDate, item.EndDate, frequency); _timeRangeCache[rangeTuple] = timeRange; } var valuesBuilder = new SeriesBuilder <DateTime, double>(); int valueIndex = 0; foreach (var valueItem in item.Values) { if (valueItem != null) { valuesBuilder.Add(timeRange[valueIndex], Convert.ToDouble(valueItem)); } valueIndex++; } var values = new TimeSeriesValues( item, frequency, new AttributesMap <string>(_dimensions, dimensions), new AttributesMap <object>(_attributes, attributes), valuesBuilder.Series); _values[values] = values; }
public static MovingAverageResult CalculateMovingAverage( List <DataPoint> series, int daysMovingAverage, DateTime beginDate, DateTime endDate, MovingAverageType movingAverageType = MovingAverageType.Simple) { if (daysMovingAverage <= 1) { throw new ArgumentException("daysMovingAverage has to be greater than 1"); } series = series.OrderBy(o => o.DateTime) .ToList(); List <DataPoint> collapsedSeries = series.GroupBy(g => g.DateTime) .Select(s => new DataPoint { DateTime = s.Key, Value = s.Sum(z => z.Value) }) .ToList(); SeriesBuilder <DateTime, decimal> dateSeries = new SeriesBuilder <DateTime, decimal>(); foreach (DataPoint dataPoint in collapsedSeries) { dateSeries.Add(dataPoint.DateTime, dataPoint.Value ?? 0m); } Series <DateTime, decimal> movingAverage = dateSeries .Series .Window(daysMovingAverage) .Select(s => s.Value.Mean()); List <DataPoint> movingAverageSeries = movingAverage .GetAllObservations() .Select(s => new DataPoint { DateTime = s.Key, Value = s.Value.Value, SeriesName = string.Format("{0}-day Moving Average", daysMovingAverage) }) .ToList(); series = series .Where(w => w.DateTime >= beginDate) .Where(w => w.DateTime <= endDate) .OrderBy(o => o.SeriesName) .ThenBy(o => o.DateTime) .ToList(); return(new MovingAverageResult(series, movingAverageSeries, movingAverageType)); }
private static Series <string, double> ColumnWiseSum(Frame <int, string> frame, string exclude) { var sb = new SeriesBuilder <string, double>(); foreach (string colname in frame.ColumnKeys) { double frequency = frame[colname].Sum(); if (!colname.Equals(exclude)) { sb.Add(colname, frequency); } } return(sb.ToSeries()); }
private static Frame <int, string> CreateCategories(Series <int, string> rows, string originalColName) { var categoriesByRows = rows.GetAllValues().Select((x, i) => { // Encode the categories appeared in each row with 1 var sb = new SeriesBuilder <string, int>(); sb.Add(String.Format("{0}_{1}", originalColName, x.Value), 1); return(KeyValue.Create(i, sb.Series)); }); // Create a data frame from the rows we just created // And encode missing values with 0 var categoriesDF = Frame.FromRows(categoriesByRows).FillMissing(0); return(categoriesDF); }
public static IEnumerable <Series <string, object> > ReadCsv(this string file) { // NuGet: PM> Install-Package LumenWorksCsvReader using (var csv = new CsvReader(new StreamReader(file), true)) { int fieldCount = csv.FieldCount; string[] headers = csv.GetFieldHeaders(); while (csv.ReadNextRecord()) { var seriesBuilder = new SeriesBuilder <string>(); for (int i = 0; i < fieldCount; i++) { seriesBuilder.Add(headers[i], csv[i]); } yield return(seriesBuilder.Series); } } }
public Frame <int, string> CreateLemmaVector(Series <int, string> rows) { var stanfordCoreNlp = _stanfordCoreNlpFactory.GetStanfordCoreNlp(new Dictionary <string, string>() { { "annotators", "tokenize, ssplit, pos, lemma" }, { "ner.useSUTime", "0" } }); var lemmaByRows = rows.GetAllValues().Select((term, index) => { var seriesBuilder = new SeriesBuilder <string, int>(); var annotation = new Annotation(term.Value); stanfordCoreNlp.annotate(annotation); var tokens = annotation.get(typeof(CoreAnnotations.TokensAnnotation)); var analysedTokens = (tokens as ArrayList)? .Cast <CoreLabel>() .Where(token => !_stopWords.Contains(token.lemma().ToLower())) .Select(token => token.lemma().ToLower()) .Distinct(); if (analysedTokens == null) { Console.WriteLine($" Analysed Tokens was null for term: {term.Value}"); return(KeyValue.Create(index, seriesBuilder.Series)); } foreach (var token in analysedTokens) { seriesBuilder.Add(token, 1); } return(KeyValue.Create(index, seriesBuilder.Series)); }); var lemmaVector = Frame.FromRows(lemmaByRows).FillMissing(0); return(lemmaVector); }
private ChartValues <double> AggregateByPeriod(double[] d, bool negative = true, TimeGroupers period = TimeGroupers.Monthly) { // Using a startdate of "2018-01-01" because it starts on a Monday var startDate = new DateTime(2018, 01, 01, 0, 0, 0); // Create SeriesBuilder var seriesBuilder = new SeriesBuilder <DateTime, double>(); // Iterate over each element of the array of results & create datetime index incrementally for (var i = 0; i < d.Length; i++) { seriesBuilder.Add(startDate.AddHours(i), d[i]); } // To Series. var series = seriesBuilder.Series; Series <DateTime, double> result; // Group the series by period if (period == TimeGroupers.Monthly) { result = series.GroupBy(c => new DateTime(2018, c.Key.Month, 01)) .Select(g => g.Value.Values.Sum()); } else { result = series.GroupBy(c => c.Key.Date) .Select(g => g.Value.Values.Sum()); } if (negative) { result = -result; } return(result.Values.AsChartValues()); }
// Allows intialisation code reuse //------------------------------------------------------------------------------------------------ private void initFutureSeriesBuilder(List<string> tickers, List<DateTime> daterange, List<DateTime> holidays, string futuresStaticMoniker, ICarbonClient client, string carbonEnv = "PRD", RollMethods rolMthd = RollMethods.FirstNoticeDate, InterpolationTypes interpType = InterpolationTypes.None, List<string> contractSortOrder = null , Dictionary<string,DateTime> rollmap = null, SmoothingTypes smoothingType = SmoothingTypes.None) //------------------------------------------------------------------------------------------------ { // defaults dateRange_ = daterange; startDate_ = daterange.Min(); endDate_ = daterange.Max(); carbonEnv_ = carbonEnv; rollMethod_ = rolMthd; //RollMethods.LastTradeDate; // holidays_ = holidays; futuresStaticMoniker_ = futuresStaticMoniker; interpType_ = interpType; smoothingType_ = smoothingType; if (contractSortOrder == null) { contractSortOrder_ = new List<string>(); } else { contractSortOrder_ = contractSortOrder; } if (rolMthd == RollMethods.Custom && rollmap == null) { throw new ArgumentException("Custom roll dates required for custom rolls!"); } ContractMonthLookupTable_ = new Dictionary<ContractMonths, string> { {ContractMonths.PrevFrontMonth, "PrevFront"}, {ContractMonths.FrontMonth, "Front"}, {ContractMonths.BackMonth, "Back"}, {ContractMonths.SecondBackMonth, "SecondBack"} }; Tuple<List<Tuple<string, ContractMonths>> /*rootTickers*/, List<string> /*contracts*/> tickerListTuple; // Get Static FuturesStatic = getFuturesStatic(tickers, futuresStaticMoniker, client, carbonEnv, out tickerListTuple, startDate_, endDate_, contractSortOrder_); // Add custom roll if present if (rollmap != null) { var sb = new SeriesBuilder<string,DateTime>(); foreach (var kvp in rollmap) { sb.Add(kvp.Key, kvp.Value); } FuturesStatic.AddColumn("custom_roll", sb.Series); } inputTickers_ = tickers; contractTickers_ = tickerListTuple.Item2; RollingContractSpecs_ = tickerListTuple.Item1; var contracts = FuturesStatic.RowKeys.ToList(); // get all the tickers (in case no tickers supplied // Get prices Console.WriteLine("Getting Futures prices"); RawFuturesPrices = getAllFuturesPricesInDateRange(contracts, startDate_, endDate_, client); RawFuturesPrices.Print(); // Align Futures Prices & interpolate gaps alignRawPriceFrameWithDateRange(dateRange_); //interpolateRawPriceFrame(interpType_); }
//---------------------------------------------------------------------------------------- public async static Task<Frame<DateTime, string>> GetBondPricesAsync(List<string> bonds, List<DateTime> dates, BondAnalytics.Country eCountry ) //---------------------------------------------------------------------------------------- { var opMap = new ConcurrentDictionary<DateTime, Series<string, double>>(); // Let's trigger all the data to start coming back ConcurrentDictionary<string, Task<GenericPrice>> asyncTable = new ConcurrentDictionary<string, Task<GenericPrice>>(); List<Tuple<DateTime, string>> dateBondList = new List<Tuple<DateTime, string>>(); foreach (var dte in dates) foreach (string bond in bonds) { dateBondList.Add(new Tuple<DateTime, string>(dte, bond)); } Parallel.ForEach(dateBondList, item => { DateTime dte = item.Item1; string bond = item.Item2; Console.WriteLine("Triggering async for {0}", bond + "_" + dte.ToShortDateString()); var closeSnapTup = GetCloseSnap(dte, eCountry); string closeSnap = closeSnapTup.Item1; string source = closeSnapTup.Item2; asyncTable[bond + "_" + dte.ToShortDateString()] = GetHistoryPriceAsync(bond, dte, closeSnap, source); }); // Wait for 10 secs to do its thing Thread.Sleep(PauseDuration); foreach(var dte in dates) { Console.WriteLine("Getting prices on {0}", dte.ToShortDateString()); var sb = new SeriesBuilder<string, double>(); foreach (var bond in bonds) { GenericPrice res = await asyncTable[bond + "_" + dte.ToShortDateString()]; if (res == null) { sb.Add(bond, double.NaN); } else sb.Add(bond, res.Price); } opMap[dte] = sb.Series; } var df = Frame.FromRows(opMap); df = df.SortRowsByKey(); return df; }
// GBP is only currently setup to get spot ASW terms. Will move on to futures only if it becomes necessary. //---------------------------------------------------------------------------------------- public static void run(DateTime start, DateTime end, string samplingFreq, string outputFolderPath) //---------------------------------------------------------------------------------------- { Console.WriteLine("Commencing GBP Run"); // INIT BondAnalytics.Country eCountry = BondAnalytics.Country.UK; List<string> SwapMeasures = new List<string>() { "MMS", "Spread", "TrueSpread" }; // List<string> BondMeasures = new List<string>() { "Price", "Yield"}; // FIND ALL SECURITIES. DateTime fDate = DateTime.Today.AddDays(30); List<string> rawmlptickers = DataHandler.GetAllSecurities("UKT", "Term", fDate); // Remove everything with AuC in it List<string> mlptickers = new List<string>(); foreach (string tic in rawmlptickers) { if (!tic.ToLower().Contains("auc")) { mlptickers.Add(tic); } } Console.WriteLine(); Console.WriteLine("Found UKT tickers"); foreach (string tic in mlptickers) { Console.WriteLine(tic); } // GET THE RIGHT STATICS var fcstCfg = new SpreadTimeSeriesConfigs("UK", bForecastCurve:true); var discCfg = new SpreadTimeSeriesConfigs("UK", bForecastCurve:false); var bondStaticMap = new Dictionary<string, BondStatic>(); foreach (string tic in mlptickers) { bondStaticMap[tic] = DataHandler.GetBondStatic(tic); } // GET DATES. Console.WriteLine(); Console.WriteLine("Setting Dates"); var res = DataHandler.GetCarbonClient().GetCalendarAsync("GBLO"); res.Wait(); var holsInLocalDate = res.Result.Dates; List<DateTime> hols = holsInLocalDate.Select(d => d.ToDateTime()).ToList(); DateTime startDate = start.AddTenor(Tenor.FromString("-1b"), "").AddTenor(Tenor.FromString("1b"), ""); DateTime nextDate = end.AddTenor(Tenor.FromString("1b"), "").AddTenor(Tenor.FromString("-1b"), ""); List<DateTime> dateRange = new List<DateTime>(); if (startDate > nextDate) { throw new ArgumentException("Start date cannot be after end date"); } var tenor = Tenor.FromString("-" + samplingFreq); while (nextDate >= startDate) { dateRange.Add(nextDate); nextDate = BondAnalytics.PrevBusDay(nextDate.AddTenor(tenor, ""), hols); } // GET ALL PRICES. Console.WriteLine(); Console.WriteLine("Setting Prices"); var result = DataHandler.GetBondPricesAsync(mlptickers, dateRange, eCountry); Frame<DateTime, string> bondFrame; if (result.IsCompleted) bondFrame = result.Result; else throw new ArgumentNullException("No bond prices came back!"); bondFrame.Print(); // GET ALL SWAP CURVES. Console.WriteLine(); Console.WriteLine("Getting Swap Cruves"); var fCurves = DataHandler.getDiscountCurvesInDateRangeAsync(fcstCfg.SymForecastCurveName, dateRange).Result; var dCurves = DataHandler.getDiscountCurvesInDateRangeAsync(fcstCfg.SymDiscountCurveName, dateRange).Result; // GET ALL MEASURES. var output = new Dictionary<string/*measure*/,Frame<DateTime,string>>(); var configs = new List<SpreadTimeSeriesConfigs>(){fcstCfg, discCfg}; // Swap measures foreach (string measure in SwapMeasures) { Console.WriteLine("Calculating {0}", measure); foreach (var config in configs) { Console.WriteLine("Forecast curve ? {0}", config); var valueMap = new Dictionary<string/*id*/, Series<DateTime,double>>(); bool bForecast = config.bForecastCurve; foreach (var ticker in mlptickers) { var srs = bondFrame.Columns[ticker]; var bndStatic = bondStaticMap[ticker]; var sb = new SeriesBuilder<DateTime, double>(); foreach (DateTime dte in srs.Keys) { // Skip if we're missing data somewhere if (!(dCurves.ContainsKey(dte) && srs.ContainsKey(dte))) continue; if (config.bForecastCurve && !fCurves.ContainsKey(dte)) // only press on if we need forecast curves continue; // Proceed. DiscountCurve discount = dCurves[dte]; DiscountCurve forecast = bForecast ? fCurves[dte] : discount; DateTime settle = BondAnalytics.NextBusDay(dte.Date.AddDays(config.bondSettleLag), hols); double price = srs.TryGetAs<double>(dte).OrDefault(double.NaN); if (double.IsNaN(price)) continue; double value = BondASWCalc.calcMeasure( measure, price, eCountry, dte, settle, discount, forecast, bndStatic, config, hols); if (double.IsNaN(value)) continue; sb.Add(dte, value); } valueMap[ticker] = sb.Series; Console.WriteLine("Completed for {0}", ticker); valueMap[ticker].Print(); } var df = Frame.FromColumns(valueMap); string prefix = bForecast ? "L" : "OIS"; output[prefix + measure] = df; Console.WriteLine(); Console.WriteLine("Swap Measures complete."); } } //Bond Measure foreach(string measure in BondMeasures) { var config = fcstCfg; Console.WriteLine("Calculating {0}", measure); var valueMap = new Dictionary<string/*id*/, Series<DateTime, double>>(); foreach (var ticker in mlptickers) { var srs = bondFrame.Columns[ticker]; var bndStatic = bondStaticMap[ticker]; var sb = new SeriesBuilder<DateTime, double>(); foreach (DateTime dte in srs.Keys) { // Skip if we're missing data somewhere if (!srs.ContainsKey(dte)) continue; // Proceed. DateTime settle = BondAnalytics.NextBusDay(dte.Date.AddDays(config.bondSettleLag), hols); double price = srs.TryGetAs<double>(dte).OrDefault(double.NaN); if (double.IsNaN(price)) continue; double value = BondASWCalc.calcMeasure(measure, price, eCountry, dte, settle, null, null, bndStatic, config, hols); if (double.IsNaN(value)) continue; sb.Add(dte, value); } valueMap[ticker] = sb.Series; Console.WriteLine("Completed for {0}", ticker); valueMap[ticker].Print(); } var df = Frame.FromColumns(valueMap); output[ measure] = df; Console.WriteLine(); Console.WriteLine("Bond Measures complete."); } // SAVE OUTPUT. Console.WriteLine("Saving CSV Files"); var renameMap = new Dictionary<string, string>() { {"LTrueSpread", "LOAS"}, {"OISTrueSpread", "OISOAS"}, {"LSpread", "LASW"}, {"OISSpread", "OISASW"} }; foreach (var kvp in output) { var measure = kvp.Key; var df = convertFrameToString(kvp.Value); if (renameMap.ContainsKey(measure)) { measure = renameMap[measure]; } var fileName = outputFolderPath + "\\" + eCountry.ToString()+ "_" + measure + ".csv"; df = df.FillMissing(""); df.SaveCsv(fileName,includeRowKeys:true); Console.WriteLine("Saved {0}", fileName); } }
//---------------------------------------------------------------------------------------- public static Frame<DateTime, String> GenerateRollingBondForwardSeries( List<string> tickers, DateTime start, DateTime end, string tenor, string countryCode, string measure, string holidayCode, bool bOIS = true, int optExDivDays = 0, bool bSpreadOrRepo = true, List<double> reposOrSpreads = null, ICarbonClient client = null) //---------------------------------------------------------------------------------------- { // Checks if (client == null) { throw new ArgumentException("No Carbon Client!"); } #region cache string all_tickers = ";"; foreach (var s in tickers) all_tickers += s; string allRepoOis = ""; if (reposOrSpreads != null) foreach (var s in reposOrSpreads) allRepoOis+= s; string cacheKey = "GenerateRollingBondForwardSeries" + tickers.ToString() + start.ToString() + end.ToString() + tenor + countryCode + measure + holidayCode + bOIS.ToString() + optExDivDays.ToString() + bSpreadOrRepo.ToString() + allRepoOis; if (TimeSeriesCache.ContainsKey(cacheKey)) { return TimeSeriesCache[cacheKey]; } #endregion #region Checks if (start >end) throw new ArgumentException("#Error: start date cannot be after end date"); #endregion var settings = new List<Tuple<string/*moniker*/, string/*tickercol*/, string/*pricecol*/>>(); // Get Configs foreach (var ticker in tickers) { if (ticker.Contains('.')) // it's a CTD series! { settings.Add(MonikerConfigs.getCTDMoniker(countryCode,ticker,client)); } else if (ticker.ToLower().Contains("ct")) { settings.Add(MonikerConfigs.getCTMoniker(countryCode, ticker, client)); } else { throw new ArgumentException("#Error: Invalid ticker found - " + ticker); } } #region DATA bool bHaveEverything = true; var configs = new SpreadTimeSeriesConfigs(countryCode, !bOIS); var spreadConventions = new SpreadConventions(configs); var dateRange = TimeSeriesUtilities.GetAllDatesInDateime(start, end, configs.calendarcode, client, "1b"); // Force daily sampling var fwdDates = dateRange.Select(dte => dte.AddTenor(Tenor.FromString(tenor))).ToList(); var holidays = TimeSeriesUtilities.GetHolidays(holidayCode,client); // Parcel input repo rates or spreads Series<DateTime, double> inputSrs = null; if (reposOrSpreads != null ) if (reposOrSpreads.Count != dateRange.Count && reposOrSpreads.Count != 1) { throw new ArgumentException("#Error: number of spreads or rates do not much the days in range"); } else { var sb = new SeriesBuilder<DateTime, double>(); double scale_factor = bSpreadOrRepo ? 10000 : 1; for (int i = 0; i < dateRange.Count; ++i) { if (reposOrSpreads.Count == 1) { sb.Add(dateRange[i], reposOrSpreads[0]/scale_factor); } else { sb.Add(dateRange[i], reposOrSpreads[i]/scale_factor); } } inputSrs = sb.Series; } // Swap Curves var curves = TimeSeriesUtilities.GetCurvesFromCarbon(dateRange, configs.ccy, client); if (curves == null) bHaveEverything = false; // Prices and tickers from ad-hoc persistence var frames = new Dictionary<string, Frame<DateTime, string>>(); for (int i = 0; i < tickers.Count; ++i) { var setting = settings[i]; var ticker = tickers[i]; var moniker = setting.Item1; var tickercol = setting.Item2; var pricecol = setting.Item3; var tmp_df = client.GetFrameAsync<DateTime>(moniker, "AdHocData").Result; if (tmp_df == null) { bHaveEverything = false; } else { // Extract price and ticker cols only var colsOfInterest = new Dictionary<string, Series<DateTime,object>>(); // Filter data to contain date range tmp_df = tmp_df.Where(kvp => (kvp.Key >= start) && (kvp.Key <= end)); colsOfInterest["price"] = tmp_df.GetColumn<object>(pricecol); colsOfInterest["isin"] = tmp_df.GetColumn<object>(tickercol); frames[ticker] = Frame.FromColumns(colsOfInterest); } } //Bond static var bondIsinSet = new HashSet<string>(); foreach(var kvp in frames) { var ticker = kvp.Key; var data = kvp.Value; var isins = data.GetColumn<string>("isin").Values; //isins.Select(isin => bondIsinSet.Add(isin)); foreach (string isin in isins) { bondIsinSet.Add(isin); } } var bondStatics = client.BulkGetBondStaticData( bondIsinSet.ToList()); if (curves == null || bondStatics == null ) return null; #endregion #region RepoRegion Series<DateTime, double> repoSrs = null; if (reposOrSpreads == null) { // Load default repo-OIS Spread double[,] repoRates = client.GetRepoRateFromSavedRepoOisSpread(BondAnalytics.CountryMappings[countryCode], dateRange, fwdDates, holidays); // Break out if no data if (repoRates == null) return null; var repoSrsBlder = new SeriesBuilder<DateTime, double>(); for (int i = 0; i < dateRange.Count; ++i) { repoSrsBlder.Add(dateRange[i], repoRates[i, 1]); } repoSrs = repoSrsBlder.Series; } else { // User-defined repo-OIS Spread or repo rates if (bSpreadOrRepo) { //Inputs are spreads double[,] repoRates = client.CalcRepoRatesFromOisSpread(inputSrs, BondAnalytics.CountryMappings[countryCode], dateRange, fwdDates, holidays); // Break out if no data if (repoRates == null) return null; var repoSrsBlder = new SeriesBuilder<DateTime, double>(); for (int i = 0; i < dateRange.Count; ++i) { repoSrsBlder.Add(dateRange[i], repoRates[i, 1]); } repoSrs = repoSrsBlder.Series; } else { //Inputs are repo rates repoSrs = inputSrs; } } #endregion // Calculation loop var forecastCurves = curves.Item1; var discountCurves = curves.Item2; // Overwrite forecast curve if we want OIS if (bOIS) { forecastCurves = discountCurves; } var outputs = new Dictionary<string, Series<DateTime, double>> (); foreach (string ticker in tickers) { var sb = new SeriesBuilder<DateTime, double>(); var df = frames[ticker]; var idx = df.RowKeys; var isins = df.GetColumn<string>("isin"); var prices = df.GetColumn<double>("price"); foreach (var dte in idx) { var tryisin = isins.TryGet(dte); var tryprice = prices.TryGet(dte); var tryrepo = repoSrs.TryGet(dte); if (!tryprice.HasValue || !tryisin.HasValue || !tryrepo.HasValue) continue; var isin = tryisin.Value; var price = tryprice.Value; var repo = tryrepo.Value; var fwddate = dte.AddTenor(Tenor.FromString(tenor)); var bondstatic = bondStatics[isin]; double value = double.NaN; if (measure == "Repo") { value = repo; } else { var fwdprice = BondAnalytics.CalcBondFwd(configs.country, dte, price, bondstatic.EffectiveDate, bondstatic.FirstCouponDate, bondstatic.MaturityDate, bondstatic.Coupon, bondstatic.CpnFreq, fwddate, repo, optExDivDays)[0]; if (measure == "Price") { value = fwdprice; } else { value = MeasureCalculator.calcFwdBondMeasure(measure, bondstatic, fwdprice, dte, fwddate, spreadConventions, forecastCurves, discountCurves, holidays); } } sb.Add(dte,value); } outputs[ticker] = sb.Series; } var consolidatedMeasures = Frame.FromColumns(outputs); // Cache results TimeSeriesCache[cacheKey] = consolidatedMeasures; return consolidatedMeasures; }
private static Frame<string, string> convertFrameToString(Frame<DateTime, string> input ) { var outputMap = new Dictionary<string, Series<string, double>>(); foreach (DateTime dte in input.RowKeys) { var row = input.GetRow<double>(dte); var sb = new SeriesBuilder<string, double>(); foreach (string id in row.Keys) { var value = row.TryGet(id).OrDefault(double.NaN); sb.Add(id, value); } outputMap[dte.ToString("yyyy-MM-dd")] = sb.Series; } return Frame.FromRows(outputMap); }
public static void Samples([CallerFilePath] string file = "") { var root = Path.GetDirectoryName(file); // ------------------------------------------------------------ // Creating and loading data frames // ------------------------------------------------------------ // [create-records] // Create a collection of anonymous types var rnd = new Random(); var objects = Enumerable.Range(0, 10).Select(i => new { Key = "ID_" + i.ToString(), Number = rnd.Next() }); // Create data frame with properties as column names var dfObjects = Frame.FromRecords(objects); dfObjects.Print(); // [/create-records] // [create-rows] // Generate collection of rows var rows = Enumerable.Range(0, 100).Select(i => { // Build each row using series builder & return // KeyValue representing row key with row data var sb = new SeriesBuilder <string>(); sb.Add("Index", i); sb.Add("Sin", Math.Sin(i / 100.0)); sb.Add("Cos", Math.Cos(i / 100.0)); return(KeyValue.Create(i, sb.Series)); }); // Turn sequence of row information into data frame var df = Frame.FromRows(rows); // [/create-rows] // [create-csv] // Read MSFT & FB stock prices from a CSV file var msftRaw = Frame.ReadCsv(Path.Combine(root, "../data/stocks/msft.csv")); var fbRaw = Frame.ReadCsv(Path.Combine(root, "../data/stocks/fb.csv")); // [/create-csv] msftRaw.Print(); // ------------------------------------------------------------ // Working with row and column indices // ------------------------------------------------------------ // [index-date] // Get MSFT & FB stock prices indexed by data var msft = msftRaw.IndexRows <DateTime>("Date").SortRowsByKey(); var fb = fbRaw.IndexRows <DateTime>("Date").SortRowsByKey(); // And rename columns to avoid overlap msft.RenameColumns(s => "Msft" + s); fb.RenameColumns(s => "Fb" + s); // [/index-date] // [index-cols] // Read US debt data from a CSV file var debt = Frame.ReadCsv(Path.Combine(root, "../data/us-debt.csv")); // Index by Year column and var debtByYear = debt .IndexRows <int>("Year") .IndexColumnsWith(new[] { "Year", "GDP", "Population", "Debt", "?" }); // [/index-cols] debtByYear.Print(); // ------------------------------------------------------------ // Joining and aligning data frames // ------------------------------------------------------------ // [join-inout] // Inner join (take intersection of dates) var joinIn = msft.Join(fb, JoinKind.Inner); // Outer join (take union & fill with missing) var joinOut = msft.Join(fb, JoinKind.Outer); // [/join-inout] joinIn.Print(); joinOut.Print(); Console.ReadLine(); // [join-lookup] // Shift MSFT observations by +1 hour for testing var msftShift = msft.SelectRowKeys(k => k.Key.AddHours(1.0)); // MSFT data are missing because keys do not match var joinLeftWrong = fb.Join(msftShift, JoinKind.Left); // This works! Find the value for the nearest smaller key // (that is, for the nearest earlier time with value) var joinLeft = fb.Join(msftShift, JoinKind.Left, Lookup.ExactOrSmaller); joinLeft.Print(); // [/join-lookup] // ------------------------------------------------------------ // Accessing data and series operations // ------------------------------------------------------------ // [series-get] // Get MSFT and FB opening prices and calculate the difference var msOpen = joinIn.GetColumn <double>("MsftOpen"); var msClose = joinIn.GetColumn <double>("MsftClose"); var msDiff = msClose - msOpen; // [/series-get] // [series-dropadd] // Drop series from a data frame joinIn.DropColumn("MsftAdj Close"); joinIn.DropColumn("FbAdj Close"); // Add new series to a frame joinIn.AddColumn("MsftDiff", msDiff); joinIn.Print(); // [/series-dropadd] // [series-rows] // Get row and then look at row properties var row = joinIn.Rows[new DateTime(2013, 1, 4)]; var msLo = row.GetAs <double>("MsftLow"); var msHi = row.GetAs <double>("MsftHigh"); // Get row for the first available value after // the specified key (1 January 2013) var firstJan = joinIn.Rows.Get(new DateTime(2013, 1, 1), Lookup.ExactOrGreater); // Get value for a specified column & row keys var diff = joinIn["MsftDiff", new DateTime(2013, 1, 4)]; // [/series-rows] // ------------------------------------------------------------ // LINQ to data frame // ------------------------------------------------------------ // [linq-select] // Project rows into a new series using the Select method var diffs = joinIn.Rows.Select(kvp => kvp.Value.GetAs <double>("MsftOpen") - kvp.Value.GetAs <double>("FbOpen")); // [/linq-select] // [linq-where] // Filter rows using a specified condition var msftGreaterRows = joinIn.Rows.Where(kvp => kvp.Value.GetAs <double>("MsftOpen") > kvp.Value.GetAs <double>("FbOpen")); // Transform row collection into a new data frame var msftGreaterDf = Frame.FromRows(msftGreaterRows); // [/linq-where] // [ops-returns] // Calculate daily returns in percents var returns = msft.Diff(1) / msft * 100.0; // Transform all numerical series // (round the values to 2 fractional digits) var round = returns.ColumnApply((Series <DateTime, double> numeric) => numeric.Select(kvp => Math.Round(kvp.Value, 2))); // [/ops-returns] round.Print(); }
//------------------------------------------------------------------------------------------------ public Frame<DateTime, string> interpolateRawPriceFrame(Frame<DateTime, string> df, InterpolationTypes interpType) //------------------------------------------------------------------------------------------------ { int frameLength = df.RowCount; int columnCount = df.ColumnCount; var columns = RawFuturesPrices.Columns; if (interpType == InterpolationTypes.None) return df; Dictionary<string, Series<DateTime, double>> resList = new Dictionary<string, Series<DateTime, double>>(); foreach (string colName in RawFuturesPrices.ColumnKeys) { var srs = columns[colName]; var idx = df.RowKeys.ToList(); double prev = double.NaN; idx.Sort(); // Find first non-NaN number List<int> startIndices = new List<int>(); List<int> endIndices = new List<int>(); SeriesBuilder<DateTime, double> sb = new SeriesBuilder<DateTime, double>(); // Forward pass for start idx int validIdx = -1; for (int i = 0; i < frameLength; ++i) { double current = srs.TryGetAs<double>(idx[i]).OrDefault(double.NaN); // Interpolate if missing if (!double.IsNaN(current)) { validIdx = i; //continue; } startIndices.Add(validIdx); } // Backward pass for end idx validIdx = -1; for (int i = frameLength-1; i >= 0; --i) { double current = srs.TryGetAs<double>(idx[i]).OrDefault(double.NaN); // Interpolate if missing if (!double.IsNaN(current)) { validIdx = i; //continue; } endIndices.Add(validIdx); } endIndices.Reverse(); // Run over and do interpolation for (int i = 0; i < frameLength; ++i) { int startidx = startIndices[i]; int endidx = endIndices[i]; double current = double.NaN; DateTime dte = idx[i]; // Cases for interpolation.... if (startidx == -1) { // Just take last price if it's there if (endidx == -1) continue; else { startidx = endidx; } } if (endidx == -1) { endidx = startidx; } if (startidx == endidx) { current = srs.GetAs<double>(idx[startidx]); } else { switch (interpType) { case InterpolationTypes.Linear: DateTime startDate = idx[startidx]; DateTime endDate = idx[endidx]; double startValue = srs.GetAs<double>(startDate); double endValue = srs.GetAs<double>(endDate); current = startValue + (endValue - startValue)* (dte - startDate).TotalDays / (endDate - startDate).TotalDays; break; case InterpolationTypes.FlatForward: current = srs.GetAs<double>(idx[startidx]); break; default: throw new ArgumentException("Illegal interpolation type (we shouldn't be here...)"); } } sb.Add(dte, current); } resList[colName] = sb.Series; } df = Frame.FromColumns(resList); return df; }
private static Frame <int, string> CreateWordVec(Series <int, string> rows, ISet <string> stopWords, bool useLemma = false) { // Path to the folder with models extracted from `stanford-corenlp-<version>-models.jar` var jarRoot = @"<path-to-model-files-dir>"; // Annotation pipeline configuration var props = new Properties(); props.setProperty("annotators", "tokenize, ssplit, pos, lemma"); props.setProperty("ner.useSUTime", "0"); // We should change current directory, so StanfordCoreNLP could find all the model files automatically var curDir = Environment.CurrentDirectory; Directory.SetCurrentDirectory(jarRoot); var pipeline = new StanfordCoreNLP(props); Directory.SetCurrentDirectory(curDir); var wordsByRows = rows.GetAllValues().Select((x, i) => { var sb = new SeriesBuilder <string, int>(); // Annotation var annotation = new Annotation(x.Value); pipeline.annotate(annotation); var tokens = annotation.get(typeof(CoreAnnotations.TokensAnnotation)); ISet <string> terms = new HashSet <string>(); foreach (CoreLabel token in tokens as ArrayList) { string lemma = token.lemma().ToLower(); string word = token.word().ToLower(); string tag = token.tag(); //Console.WriteLine("lemma: {0}, word: {1}, tag: {2}", lemma, word, tag); // Filter out stop words and single-charater words if (!stopWords.Contains(lemma) && word.Length > 1) { if (!useLemma) { terms.Add(word); } else { terms.Add(lemma); } } } foreach (string term in terms) { sb.Add(term, 1); } return(KeyValue.Create(i, sb.Series)); }); // Create a data frame from the rows we just created // And encode missing values with 0 var wordVecDF = Frame.FromRows(wordsByRows).FillMissing(0); return(wordVecDF); }
combineFuturesAndBondStatic(Dictionary<string/*isin*/, TimeSeriesBondStatic> bondstatic, Frame<string,string> futstatic) //------------------------------------------------------------------------------------------------ { bool bDeliverable = (bondstatic.Count != 0); // for non deliverable contracts, we don't feed in any bond static info var rowList = new List<KeyValuePair<int/*id*/, Series<string, object>/*row*/>>(); int i = 0; foreach (var kvp in bondstatic) { TimeSeriesBondStatic staticRow = kvp.Value; var sb = new SeriesBuilder<string>(); sb.Add("ISIN", staticRow.ISIN); sb.Add("Maturity", staticRow.Maturity.ToShortDateString()); sb.Add("EffectiveDate", staticRow.EffectiveDate.ToShortDateString()); sb.Add("FirstCouponDate", staticRow.FirstCouponDate.ToShortDateString()); sb.Add("Coupon", staticRow.Coupon); rowList.Add(KeyValue.Create(i, sb.Series)); ++i; } var df = Frame.FromRows(rowList); var bonddf = df.IsEmpty? null :df.IndexRows<string>("ISIN"); // Change indexing structure to deal with futures Dictionary<string, Series<string, object>> outputRows = new Dictionary<string, Series<string, object>>(); foreach (string colkey in futstatic.RowKeys) { var row = futstatic.Rows[colkey]; string ctdisin = row.GetAs<string>("fut_ctd_isin"); // Let's check to make sure that all EffectiveDate, FirstCouponDate,Maturity etc are on the table // and ignore the bond static if so. DateTime maturity = row.TryGetAs<DateTime>("maturity").OrDefault(DateTime.MinValue); DateTime effDate = row.TryGetAs<DateTime>("eff_dt").OrDefault(DateTime.MinValue); DateTime firstCpnDate = row.TryGetAs<DateTime>("first_cpn_dt").OrDefault(DateTime.MinValue); double coupon = row.TryGetAs<double>("cpn").OrDefault(double.NaN); if ( (maturity == DateTime.MinValue || effDate == DateTime.MinValue || firstCpnDate == DateTime.MinValue || double.IsNaN(coupon) ) && bDeliverable) { var bondstaticSrs = bonddf.Rows[ctdisin]; outputRows[colkey] = row.Merge(bondstaticSrs); } else { var sb = new SeriesBuilder<string>(); sb.Add("ISIN", ctdisin); sb.Add("Maturity", (maturity != DateTime.MinValue)? maturity.ToShortDateString():"-"); sb.Add("EffectiveDate", (effDate != DateTime.MinValue)? effDate.Date.ToShortDateString() :"-"); sb.Add("FirstCouponDate", (firstCpnDate != DateTime.MinValue) ? firstCpnDate.ToShortDateString():"-"); sb.Add("Coupon", coupon); outputRows[colkey] = row.Merge(sb.Series); } } var output = Frame.FromRows(outputRows.AsEnumerable()); //Log_.InfoFormat("Static Combined"); //output.Print(); return output.IndexRows<string>("ticker", keepColumn:true); }
//------------------------------------------------------------------------------------------------ public static Frame<string, string> sortFrameByInput(Frame<string, string> input, List<string> tickers) //------------------------------------------------------------------------------------------------ { Frame<string, string> output = input; // Make a colums to sort on var sb = new SeriesBuilder<string>(); int i = 0; foreach (string ticker in tickers) { sb.Add(ticker, i.ToString()); ++i; } // Format Output output.AddColumn("SortOrder", sb.Series); var sortDF = output.IndexRows<int>("SortOrder").SortRowsByKey(); //sortDF.Print(); output = sortDF.IndexRows<string>("ticker", keepColumn: true); //output.Print(); return output; }
//---------------------------------------------------------------------------------------------------------------------------------- public static object[,] AggregateBasisRisk(object[,] DataTable, object[,] Filters, object[,] FuturesTable, object[,] PriceTable, string Country, double dv01Scaling, bool bLiveOrEOD, string Currency, bool bInclSnED) //---------------------------------------------------------------------------------------------------------------------------------- { // WARNING: This is a very case specific tactical function. Used in the BasisPositionAndRisk sheet to aggregate risk. try { // Init data frames. Frame<string, string> dataFrame = MainHelpers.getDeedleFrameFromObjectArray(DataTable); Frame<string, string> filtersFrame = MainHelpers.getDeedleFrameFromObjectArray(Filters, hasHeader: false, hasIndex: true); Frame<string, string> futuresFrame = MainHelpers.getDeedleFrameFromObjectArray(FuturesTable); futuresFrame = futuresFrame.IndexRows<string>("Contract", keepColumn: true); Frame<string, string> priceFrame = MainHelpers.getDeedleFrameFromObjectArray(PriceTable); priceFrame = priceFrame.Where( kvp => (kvp.Value.TryGetAs<string>("Bond").ValueOrDefault != null) && (kvp.Value.TryGetAs<string>("Bond").ValueOrDefault != "ExcelErrorNA")); priceFrame = priceFrame.IndexRows<string>("Bond", keepColumn: true); Frame<string, string> aggregateFrame; #region InputValidation // Pull out all column names into sets. var dataHeaders = dataFrame.ColumnKeys.ToDictionary(v => v, v => "DataTable"); // we'll use the values for error handling later var filterRows = filtersFrame.RowKeys.ToDictionary(v => v, v => "Filter Rows"); var futuresHeaders = futuresFrame.ColumnKeys.ToDictionary(v => v, v => "FuturesTable"); var priceHeaders = priceFrame.ColumnKeys.ToDictionary(v => v, v => "PriceTable"); // Hardcoded input name requirements, and OT report generated has to conform to this; List<string> dataHeaderEssentials = new List<string>() { "Entity", "B:Strategy Type", "B:Strategy Sub Type", "B:Portfolio", "B:Strategy", "Curve Currency", "Curve Description", "Product Type", "Description", "Maturity Date", "Current Notional", "S:Country Of Risk", "S:ISIN", "Delta" }; List<string> dataHeaderRenames = new List<string>() { "Entity", "StrategyType", "StrategySubType", "Portfolio", "Strategy", "Currency", "CurveDescription", "ProductType", "Description", "Bond Maturity", "Current Notional", "CountryOfRisk", "ISIN", "Delta" }; List<string> filterRowEssentials = new List<string>() { "Entity", "StrategyType", "StrategySubType", "Portfolio", "Strategy", }; List<string> futuresHeaderEssentials = new List<string>() { "Contract", "Bond", "ISIN", "Future Quotes", "Bond Quotes", "Contract Type", "Maturity" }; List<string> priceHeaderEssentials = new List<string>() { "Bond", "S:ISIN", "PositionPrice", "ClosePrice" }; List<string> validInstruments = new List<string>() { "Bond", "BondFuture" }; if (bInclSnED) { validInstruments.Add("Swap"); validInstruments.Add("InterestFuture"); } // CHECK KEY HEADERS. List<Tuple<List<string>, Dictionary<string, string>>> checkList = new List <Tuple<List<string>, Dictionary<string, string>>>() { new Tuple<List<string>, Dictionary<string, string>>(dataHeaderEssentials, dataHeaders), new Tuple<List<string>, Dictionary<string, string>>(futuresHeaderEssentials, futuresHeaders), new Tuple<List<string>, Dictionary<string, string>>(filterRowEssentials, filterRows), new Tuple<List<string>, Dictionary<string, string>>(priceHeaderEssentials, priceHeaders) }; foreach (var test in checkList) { List<string> essentials = test.Item1; Dictionary<string, string> header = test.Item2; foreach (string name in essentials) { if (!header.ContainsKey(name)) { //A bit of a hack, but we only needed the keys in the dictionary, and this puts the values to good use too. throw new ArgumentException("#Missing " + name + " in " + header.First().Value); } } } #endregion #region FrameInitialisaiton // Extract Essential Columns. dataFrame = dataFrame.Columns[dataHeaderEssentials]; for (int i = 0; i < dataHeaderEssentials.Count; ++i) { dataFrame.RenameColumn(dataHeaderEssentials[i], dataHeaderRenames[i]); } filtersFrame = filtersFrame.Rows[filterRowEssentials]; futuresFrame = futuresFrame.Columns[futuresHeaderEssentials]; priceFrame = priceFrame.Columns[priceHeaderEssentials]; // Construct the lookup table for filters Dictionary<string, HashSet<string>> filterMap = new Dictionary<string, HashSet<string>>(); var srsKeys = filtersFrame.RowKeys.ToList(); foreach (var filterField in srsKeys) { string fieldCSVs = filtersFrame.GetRow<string>(filterField).FirstValue(); //var tmpKeys = srs.Keys; //var tmpVals = srs.Values; //string filterField = srsKeys[ int.Parse( srs.Keys.First())]; //string fieldCSVs = srs.Values.First().ToString(); // case insensitive comparisons for filter HashSet<string> values = new HashSet<string>(fieldCSVs.Trim().Split(',').ToList()); filterMap[filterField] = values; } filterMap["ProductType"] = new HashSet<string>() {"Bond", "BondFuture"}; if (bInclSnED) { filterMap["ProductType"].Add("Swap"); filterMap["ProductType"].Add("InterestFuture"); //Currency is needed if Swap is included filterMap["Currency"] = new HashSet<string>() { Currency.ToUpper() }; } // Function is only compatible with Bonds and future instruments filterMap["CountryOfRisk"] = new HashSet<string>() {Country /*.ToLower()*/}; // Filter data table dataFrame = dataFrame.Where(kvp => { bool bOK = true; var row = kvp.Value; foreach (var keyVal in filterMap) { string field = keyVal.Key; HashSet<string> validFields = keyVal.Value; //Country for swap is empty, hence must include ccy into filtering list//this is not safe for EURO swaps!!! if (field == "CountryOfRisk" ) { var ProdType = row.TryGet("ProductType").ValueOrDefault; if (ProdType != null && (ProdType.ToString() == "Swap" || ProdType.ToString() == "InterestFuture")) continue; } var tmpRowEntry = row.TryGet(field).ValueOrDefault; string rowEntry = tmpRowEntry != null ? tmpRowEntry.ToString() : ""; // we stripped spaces while parsing the filters bOK = bOK && rowEntry != null && (validFields.Contains("*") || validFields.Contains(rowEntry)); } return bOK; }); #endregion #region DataAggregation if (dataFrame.IsEmpty) { throw new ArgumentNullException("No data present after applying filters!"); } //Rename Description region for Swap to be date only if (bInclSnED) { //Loop through each row to update the Description of Swap to expiration only var rowKeyList = dataFrame.RowKeys.ToList(); var sbuilder = new SeriesBuilder<string, string>(); foreach (var rowIndx in rowKeyList) { var currRow = dataFrame.Rows[rowIndx]; string newDescription = null; if (currRow.GetAs<string>("ProductType") == "Swap") { newDescription = currRow.GetAs<string>("Description"); //newDescription = "Swap-"+ newDescription.Substring(newDescription.LastIndexOf(" ")+1); newDescription = "Swap-" + newDescription; } else { newDescription = currRow.GetAs<string>("Description"); } sbuilder.Add(rowIndx, newDescription); } //add Description and drop original description column dataFrame.DropColumn("Description"); dataFrame.AddColumn("Description", sbuilder.Series); } // MLP Alloc Frames var fullNotionalSrs = dataFrame.GetColumn<double>("Current Notional"); var fullDataFrameKeys = dataFrame.Columns["Description"]; var fullDataFrameEntities = dataFrame.Columns["Entity"]; var mlpSrs = fullNotionalSrs.Where(kvp => fullDataFrameEntities.GetAs<string>(kvp.Key) == "MLP"); var mlpnotionals = mlpSrs.GroupBy(kvp => fullDataFrameKeys.GetAs<string>(kvp.Key)).Select(x => x.Value.Sum()); //Aggregate Notionals and Deltas of position. var dataFrameKeys = dataFrame.Columns["Description"]; var dataFrameEntities = dataFrame.Columns["Entity"]; var notionalSrs = dataFrame.GetColumn<double>("Current Notional"); var dv01Srs = dataFrame.GetColumn<double>("Delta"); var notionals = notionalSrs.GroupBy(kvp => dataFrameKeys.GetAs<string>(kvp.Key)).Select(x => x.Value.Sum()); var dv01s = dv01Srs.GroupBy(kvp => dataFrameKeys.GetAs<string>(kvp.Key)).Select(x => x.Value.Sum()); SortedDictionary<string, Series<string, object>> uniqueRows = new SortedDictionary<string, Series<string, object>>(); var rowKeys = dataFrame.RowKeys.ToList(); foreach (var rowIdx in rowKeys) { var row = dataFrame.Rows[rowIdx]; object tmp = row.Get("Description"); //for swap string prodType = row.GetAs<string>("ProductType"); string instrument = tmp == null ? "" : (string) tmp; // Get values out tmp = notionals.TryGet(instrument).ValueOrDefault; double totalNotional = tmp == null ? 0.0 : (double) tmp; tmp = dv01s.TryGet(instrument).ValueOrDefault; double totalDV01 = tmp == null ? 0.0 : (double) tmp*dv01Scaling; // Scale DV01s here tmp = mlpnotionals.TryGet(instrument).ValueOrDefault; double mlpNotional = tmp == null ? 0.0 : (double) tmp; // Create the output row here if (!uniqueRows.ContainsKey(instrument)) { #region AssignRowValues double bond01 = 0.0; double fut01 = 0.0; double swap01 = 0.0; double ED01 = 0.0; double balancesheet = 0.0; double futNotional = 0.0; double swapNotional = 0.0; double EDNotional = 0.0; double totNotional = 0.0; double MLPAlloc = 0.0; double prevfront = 0.0; double front = 0.0; double back = 0.0; double back2 = 0.0; DateTime bondMaturity; string stmp = row.TryGetAs<string>("Bond Maturity").ValueOrDefault; try { //try to convert this to datetime direct bondMaturity = DateTime.ParseExact(stmp, "MM/dd/yyyy", System.Globalization.CultureInfo.InvariantCulture); } catch { //Otherwise, just pull straight bondMaturity = DateTime.FromOADate(row.TryGetAs<Double>("Bond Maturity").ValueOrDefault); } var futRow = futuresFrame.TryGetRow<string>(instrument).ValueOrDefault; if (futRow != null) { futNotional = totalNotional; fut01 = totalDV01; double dateNum = 0.0; bool parsed = double.TryParse(futRow.TryGet("Maturity").ValueOrDefault, out dateNum); bondMaturity = parsed? DateTime.FromOADate(dateNum) : DateTime.MinValue; } else if(prodType == "Swap") { //Duplicated records due to exposure to different curve risk //Not suitable for GBP swaps since GBP swaps can have exposure to 3 curves if (instrument.Contains("IBOR") && !instrument.Contains("FEDFUNDS")) { totalNotional = totalNotional / 2; mlpNotional = mlpNotional / 2; } swapNotional = totalNotional; swap01 = totalDV01; } else if(prodType == "InterestFuture") { if (instrument.Contains("Eurodollar") || instrument.Contains("Euribor")) { totalNotional = totalNotional / 2; mlpNotional = mlpNotional / 2; } if (instrument.Contains("Sterling")) { totalNotional = totalNotional / 3; mlpNotional = mlpNotional / 3; } EDNotional = totalNotional; ED01 = totalDV01; } else { var isin = priceFrame.Columns["S:ISIN"].GetAs<string>(instrument); var ctdRows = futuresFrame.Where(x => x.Value.GetAs<string>("ISIN") == isin); string priceCol = bLiveOrEOD ? "PositionPrice" : "ClosePrice"; double price = priceFrame.Columns[priceCol].TryGetAs<double>(instrument).OrDefault(0.0); if (!ctdRows.IsEmpty) { var ctdRow = ctdRows.GetRowAt<string>(0); string ctdMonth = ctdRow.Get("Contract Type"); switch (ctdMonth) { case "FM-1": prevfront = totalDV01; break; case "FM1": front = totalDV01; break; case "BM1": back = totalDV01; break; case "BM2": back2 = totalDV01; break; default: bond01 = totalDV01; SLog.log.WarnFormat( "{0} is CTD, but contract month isn' specified. Defaulting to bond 01", instrument); break; } } else { bond01 = totalDV01; } balancesheet = price*totalNotional; } MLPAlloc = mlpNotional / totalNotional; #endregion // Processing data #region BuildRow // Create entry if doesn't exist var sb = new SeriesBuilder<string, object>(); string addOn = bLiveOrEOD ? "" : "EOD"; sb.Add("CountryOfRisk" + addOn, row.TryGet("CountryOfRisk").ValueOrDefault); if (bInclSnED) sb.Add("Product Type" + addOn, row.TryGet("ProductType").ValueOrDefault); sb.Add("BondMaturity" + addOn, bondMaturity); sb.Add("Description" + addOn, instrument); sb.Add("ISIN" + addOn, row.TryGet("ISIN").ValueOrDefault); sb.Add("Bond DV01" + addOn, bond01); sb.Add("Fut DV01" + addOn, fut01); if (bInclSnED) { sb.Add("Swap DV01" + addOn, swap01); sb.Add("Interest Future DV01" + addOn, ED01); } sb.Add("Total DV01" + addOn, totalDV01); sb.Add("Bond BalanceSheet" + addOn, balancesheet); sb.Add("Fut Notional" + addOn, futNotional); if (bInclSnED) { sb.Add("Swap Notional" + addOn, swapNotional); sb.Add("Interest Future Notional" + addOn, EDNotional); } sb.Add("Total Notional" + addOn, totalNotional); sb.Add("MLP Allocation" + addOn, MLPAlloc); sb.Add("FM-1" + addOn, prevfront); sb.Add("FM1" + addOn, front); sb.Add("BM1" + addOn, back); sb.Add("BM2" + addOn, back2); uniqueRows[bondMaturity.ToShortDateString() + "_" + instrument] = sb.Series; #endregion } } #endregion // Package outputs string appendix = bLiveOrEOD ? "" : "EOD"; aggregateFrame = Frame.FromRows(uniqueRows.AsEnumerable()); aggregateFrame = FrameExtensions.SortRows(aggregateFrame, "BondMaturity" + appendix); var output = MainHelpers.getFrameAsObjArr(aggregateFrame, sortkeys: false); output[0, 0] = "ID"; return output; } catch (Exception ex) { SLog.log.ErrorFormat("Error in SymAggregateBasisRiskReportData(): {0}", ex.Message); // RETURN HEADERS, to avoid messing pivot charts up // Create entry if doesn't exist var sb = new SeriesBuilder<string, object>(); string addOn = bLiveOrEOD ? "" : "EOD"; sb.Add("CountryOfRisk" + addOn, "#Error"); sb.Add("BondMaturity" + addOn, "#Error"); sb.Add("Description" + addOn, "#Error"); sb.Add("ISIN" + addOn, "#Error"); sb.Add("Bond DV01" + addOn, "#Error"); sb.Add("Fut DV01" + addOn, "#Error"); if (bInclSnED) { sb.Add("Swap DV01" + addOn, "#Error"); sb.Add("Interest Future DV01" + addOn, "Error"); } sb.Add("Total DV01" + addOn, "#Error"); sb.Add("Bond BalanceSheet" + addOn, "#Error"); sb.Add("Fut Notional" + addOn, "#Error"); if (bInclSnED) { sb.Add("Swap Notional" + addOn, "#Error"); sb.Add("Interest Future Notional" + addOn, "#Error"); } sb.Add("Total Notional" + addOn, "#Error"); sb.Add("MLP Allocation" + addOn, "#Error"); sb.Add("FM-1" + addOn, "#Error"); sb.Add("FM1" + addOn, "#Error"); sb.Add("BM1" + addOn, "#Error"); sb.Add("BM2" + addOn, "#Error"); SortedDictionary<string, Series<string, object>> uniqueRows = new SortedDictionary<string, Series<string, object>>(); uniqueRows["Error"] = sb.Series; string appendix = bLiveOrEOD ? "" : "EOD"; Frame<string, string> aggregateFrame = Frame.FromRows(uniqueRows.AsEnumerable()); aggregateFrame = FrameExtensions.SortRows(aggregateFrame, "BondMaturity" + appendix); var output = MainHelpers.getFrameAsObjArr(aggregateFrame, sortkeys: false); output[0, 0] = "ID"; return output; } }
//------------------------------------------------------------------------------------------------ public Frame<DateTime, string> computeFuturesSpreads() //------------------------------------------------------------------------------------------------ { Log_.InfoFormat("Computing spreads..."); CombinedStatic = SpreadSeriesBuilder.combineFuturesAndBondStatic(BondStatic,FuturesStatic); var columns = FuturesPrices.Columns; FrameBuilder.Columns<DateTime, string> frameblder = new FrameBuilder.Columns<DateTime, string>(); // Iterate over columns for prices foreach (var col in FuturesPrices.ColumnKeys) { var series = columns[col].As<double>(); //series = series.Select(kvp => calcFuturesMeasure(SpreadMetric_, col, kvp.Value, kvp.Key)); var dte_idx = series.Keys.ToList(); SeriesBuilder<DateTime,double> sb = new SeriesBuilder<DateTime, double>(); Tuple<DateTime, double> prev = null; /* THIS ABSOLUTELY HAS TO BE IN ASCENDING ORDER */ dte_idx.Sort(); foreach(var dte in dte_idx) { var res = series.TryGet(dte); if (res.HasValue) { double price = res.Value; var staticRow = CombinedStatic.Rows.TryGet(col).ValueOrDefault; /* This section is to account for deficiencies in our database. */ // Quit if we don't have static if (staticRow == null) { sb.Add(dte, double.NaN); continue; } // Quit if we have a bad price if (price == 0.0) { sb.Add(dte, double.NaN); continue; } // Quit if contract isn't even trading var firstTradeDate = staticRow.GetAs<DateTime>("fut_first_trade_dt"); var lastTradeDate = staticRow.GetAs<DateTime>("last_tradeable_dt"); if (dte > lastTradeDate || dte < firstTradeDate) { sb.Add(dte, double.NaN); continue; } // Get price for AUD if (Conv_.Country == BondAnalytics.Country.AU) { DateTime maturity = TimeSeriesUtilities.LazySafeTryGetAs(staticRow, "Maturity", DateTime.MinValue); int tenor = (int)Math.Round((maturity - dte).Days / 365.25); price = BondAnalytics.CalcAUDFuturesContractValue(price, tenor); } // ASSUMPTION: Our DB seems to front fill by default. Skip days where no data is present /*if (prev != null && price == prev.Item2) { sb.Add(dte, double.NaN); continue; } */ double metric = calcFuturesMeasure(SpreadMetric_, col, price, dte, previous: prev); prev = new Tuple<DateTime, double>(dte, price); sb.Add(dte, metric); } else { sb.Add(dte, double.NaN); } } frameblder.Add(col, sb.Series); } var output = frameblder.Frame; Log_.InfoFormat("Complete:"); //output.Print(); return output.SortRowsByKey(); }
public static void Samples([CallerFilePath] string file = "") { var root = Path.GetDirectoryName(file); // ------------------------------------------------------------ // Creating and loading data frames // ------------------------------------------------------------ // [create-records] // Create a collection of anonymous types var objects = Enumerable.Range(0, 100).Select(i => new { Group = "g" + (i/10).ToString(), Number = i }); // Create data frame with properties as column names var dfObjects = Frame.FromRecords(objects); dfObjects.Print(); // [/create-records] // [create-rows] // Generate collection of rows var rows = Enumerable.Range(0, 100).Select(i => { // Build each row using series builder & return // KeyValue representing row key with row data var sb = new SeriesBuilder<string>(); sb.Add("Index", i); sb.Add("Sin", Math.Sin(i / 100.0)); sb.Add("Cos", Math.Cos(i / 100.0)); return KeyValue.Create(i, sb.Series); }); // Turn sequence of row information into data frame var df = Frame.FromRows(rows); // [/create-rows] // [create-csv] // Read MSFT & FB stock prices from a CSV file var msftRaw = Frame.ReadCsv(Path.Combine(root, "../data/stocks/msft.csv")); var fbRaw = Frame.ReadCsv(Path.Combine(root, "../data/stocks/fb.csv")); // [/create-csv] // ------------------------------------------------------------ // Working with row and column indices // ------------------------------------------------------------ // [index-date] // Get MSFT & FB stock prices indexed by data var msft = msftRaw.IndexRows<DateTime>("Date").OrderRows(); var fb = fbRaw.IndexRows<DateTime>("Date").OrderRows(); // And rename columns to avoid overlap msft.RenameSeries(s => "Msft" + s); fb.RenameSeries(s => "Fb" + s); // [/index-date] // [index-cols] // Read US debt data from a CSV file var debt = Frame.ReadCsv(Path.Combine(root, "../data/us-debt.csv")); // Index by Year column and var debtByYear = debt .IndexRows<int>("Year") .IndexColumnsWith(new[] { "Year", "GDP", "Population", "Debt", "?" }); // [/index-cols] // ------------------------------------------------------------ // Joining and aligning data frames // ------------------------------------------------------------ // [join-inout] // Inner join (take intersection of dates) var joinIn = msft.Join(fb, JoinKind.Inner); // Outer join (take union & fill with missing) var joinOut = msft.Join(fb, JoinKind.Outer); // [/join-inout] // [join-lookup] // Shift MSFT observations by +1 hour for testing var msftShift = msft.SelectRowKeys(k => k.Key.AddHours(1.0)); // MSFT data are missing because keys do not match var joinLeftWrong = fb.Join(msftShift, JoinKind.Left); // This works! Find the value for the nearest smaller key // (that is, for the nearest earlier time with value) var joinLeft = fb.Join(msftShift, JoinKind.Left, Lookup.NearestSmaller); joinLeft.Print(); // [/join-lookup] // ------------------------------------------------------------ // Accessing data and series operations // ------------------------------------------------------------ // [series-get] // Get MSFT and FB opening prices and calculate the difference var msOpen = joinIn.GetSeries<double>("MsftOpen"); var msClose = joinIn.GetSeries<double>("MsftClose"); var msDiff = msClose - msOpen; // [/series-get] // [series-dropadd] // Drop series from a data frame joinIn.DropSeries("MsftAdj Close"); joinIn.DropSeries("FbAdj Close"); // Add new series to a frame joinIn.AddSeries("MsftDiff", msDiff); joinIn.Print(); // [/series-dropadd] // [series-rows] // Get row and then look at row properties var row = joinIn.Rows[new DateTime(2013, 1, 4)]; var msLo = row.GetAs<double>("MsftLow"); var msHi = row.GetAs<double>("MsftHigh"); // Get value for a specified column & row keys var diff = joinIn["MsftDiff", new DateTime(2013, 1, 4)]; // [/series-rows] // ------------------------------------------------------------ // LINQ to data frame // ------------------------------------------------------------ // [linq-select] // Project rows into a new series using the Select method var diffs = joinIn.Rows.Select(kvp => kvp.Value.GetAs<double>("MsftOpen") - kvp.Value.GetAs<double>("FbOpen")); // [/linq-select] // [linq-where] // Filter rows using a specified condition var msftGreaterRows = joinIn.Rows.Where(kvp => kvp.Value.GetAs<double>("MsftOpen") > kvp.Value.GetAs<double>("FbOpen")); // Transform row collection into a new data frame var msftGreaterDf = Frame.FromRows(msftGreaterRows); // [/linq-where] }
getFuturesStatic(List< string> tickers , string futuresStaticMoniker, ICarbonClient client, string carbonEnv, out Tuple<List<Tuple<string, ContractMonths>> /*rootTickers*/, List<string> /*contracts*/> tickerSplitTuple, DateTime? vStartDate = null, DateTime? vEndDate = null, List<string> contractSortOrder = null ) //------------------------------------------------------------------------------------------------ { // Intialisation if (tickers == null) { tickers = new List<string>(); } DateTime startDate, endDate; if (vStartDate == null) { startDate = DateTime.MinValue; } else { startDate = vStartDate.Value; } if (vStartDate == null) { endDate = DateTime.MaxValue; } else { endDate = vEndDate.Value; } if (contractSortOrder == null) { contractSortOrder = new List<string>(); } string cacheKey = getCacheKey(tickers, futuresStaticMoniker, startDate, endDate, contractSortOrder); // Divide inputs according to whether they should be used for rolling futures or not tickerSplitTuple = splitRollingFuturesFromRawTickers(tickers); List<string> contractTickers = tickerSplitTuple.Item2; List<Tuple<string, ContractMonths>> rootTickers = tickerSplitTuple.Item1; // Get Static From cache here if we have it, tickersplittuple has been set. Frame<string, string> cachedValue; if (StaticCache_.TryGetValue(cacheKey, out cachedValue)) return cachedValue; // Get all the roots from list List< string> rollingFuturesIDs = new List<string>(); foreach (var tup in rootTickers) { rollingFuturesIDs.Add(tup.Item1); } // Get test sets. // This allows us to map back names used in futures static moniker, to our original inputs var bbgTickerMap = processBBGTickerList(contractTickers); HashSet<string> rollingSet = new HashSet<string>(rollingFuturesIDs); HashSet<string> tickerSet = new HashSet<string>(bbgTickerMap.Keys.AsEnumerable()); // Processing inputs Frame<string, string> output; var rowList = new List<KeyValuePair<int/*id*/, Series<string, object>/*row*/>>(); var df = client.GetDataFrame(futuresStaticMoniker); var tmp = df.ToList(); var col = tmp[0].Value as List<object>; var ind = tmp[1].Value as List<object>; var dat = tmp[2].Value as List<object>; //Find it's first trade date col int firstTradeDtCol = 0; int futDeliveryDtCol = 0; int typeCol = 0; for (int j = 0; j < col.Count; ++j) { string heading = col[j].ToString(); if (heading == "fut_first_trade_dt") { firstTradeDtCol = j; } if (heading == "fut_dlv_dt_last") { futDeliveryDtCol = j; } if(heading == "type") { typeCol = j; } } //client.getdat SeriesBuilder<string> sb; int i; for (i = 0; i < ind.Count; ++i) { sb = new SeriesBuilder<string>(); var data = dat[i] as List<object>; var contract = data[typeCol].ToString(); string index = (string)ind[i]; if ((tickerSet.IsEmpty() && rollingSet.IsEmpty()) || (!tickerSet.Contains(index) && !rollingSet.Contains(contract))) { continue; } DateTime firstTradeDate = DateTime.ParseExact(data[firstTradeDtCol].ToString(), "%dd/%MM/%yyyy", CultureInfo.InvariantCulture); DateTime futDeliveryDate = DateTime.ParseExact(data[futDeliveryDtCol].ToString(), "%dd/%MM/%yyyy", CultureInfo.InvariantCulture); if (rollingSet.Contains(contract) && (futDeliveryDate < startDate || firstTradeDate > endDate)) { continue; } if (bbgTickerMap.ContainsKey(index)) sb.Add("ticker", bbgTickerMap[index]); else sb.Add("ticker", index); // ignores the mappings, in the rolling contract case for (int h = 0; h < col.Count; ++h) { sb.Add((string)col[h], data[h]); } rowList.Add(KeyValue.Create(i, sb.Series)); } output = Frame.FromRows(rowList).IndexRows<string>("ticker", keepColumn: true); if (rootTickers.IsEmpty()) { output = sortFrameByInput(output, tickers); } else { output = sortFrameByNaturalOrder(output, contractSortOrder); } StaticCache_.TryAdd(cacheKey, output.Clone()); return output; }
//------------------------------------------------------------------------------------------------ public void setRollingFuturesPrices(string outputfilepath = "") //------------------------------------------------------------------------------------------------ { Console.WriteLine("Setting Rolling Futures:"); var clonedPrices = TimeSeriesUtilities.DeepDeedleClone<DateTime, string, double>(RawFuturesPrices); double offset = 0.0; // how much to shift the entire series by // Compute the differences instead if (smoothingType_ != SmoothingTypes.None) { clonedPrices = interpolateRawPriceFrame(clonedPrices, InterpolationTypes.FlatForward); // required to calculate differences correctly clonedPrices = clonedPrices.SortRowsByKey(); clonedPrices = clonedPrices.Diff(1); // assume we do have all the required dates, as per calendar specified } // Init int i = 0; var rowList = new List<KeyValuePair<int/*id*/, Series<string, object>/*row*/>>(); var contracts = getTypesOfFuturesContracts(); foreach (string contract in contracts) { // Get only the statics for a particular type var contractSubset = FuturesStatic.Where(kvp => kvp.Value.GetAs<string>("type") == contract); // Start adding to builder foreach (DateTime dte in dateRange_) { var contractsByMonth = getXMonthContracts(dte, contractSubset, rollMethod_); // roll on first notice date Console.WriteLine("{0}: prevFM = {1}, FM = {2}, BM = {3}, BM2 = {4}", dte.ToShortDateString(), contractsByMonth[ContractMonths.PrevFrontMonth], contractsByMonth[ContractMonths.FrontMonth], contractsByMonth[ContractMonths.BackMonth], contractsByMonth[ContractMonths.SecondBackMonth]); // Add an entry for each futures contract month foreach (KeyValuePair<ContractMonths, string/*ticker*/> entry in contractsByMonth) { ContractMonths contractMonth = entry.Key; string ticker = entry.Value; if (ticker == "") { continue; } var priceRow = clonedPrices.TryGetRow<double>(dte).ValueOrDefault; double price = (priceRow == null) ? double.NaN : priceRow.TryGet(ticker).ValueOrDefault; var staticRow = FuturesStatic.GetRow<string>(ticker); // All formats here: if (price != 0.0 || smoothingType_ != SmoothingTypes.None) // so the flat forward bits get picked up { var sb = new SeriesBuilder<string>(); sb.Add("date", dte); sb.Add("deliverydate", staticRow.Get(getRollField(RollMethods.DeliveryDate))); sb.Add("rolldate", staticRow.Get(getRollField(rollMethod_))); sb.Add("ticker", ticker); sb.Add("type", staticRow.Get("type")); sb.Add("contractmonth", contractMonth.ToString()); sb.Add("price", price); sb.Add("convfact", staticRow.Get("fut_cnvs_factor")); sb.Add("ctdisin", staticRow.Get("fut_ctd_isin")); sb.Add("ctdmaturity", staticRow.Get("maturity")); sb.Add("ctdcoupon", staticRow.Get("cpn")); rowList.Add(KeyValue.Create(i, sb.Series)); ++i; } } } } RollingFuturesData = Frame.FromRows(rowList); // This needs to be reassembled in a different function Console.WriteLine("Rolled Series"); RollingFuturesData.Print(); if (outputfilepath != "") { RollingFuturesData.SaveCsv("RollingFuturesDump.csv"); clonedPrices.SaveCsv("RawFutures.csv"); } }
//---------------------------------------------------------------------------------------- public static Frame<DateTime, string> SymBondFwdTimeSeries( string[] BondId, DateTime StartDate, DateTime EndDate, String TenorString, DateTime FwdDate, object[,] SpreadOrPrice, String Measure, Boolean bOIS, Boolean bSpread, List<DateTime> Holidays) //---------------------------------------------------------------------------------------- { bool bHaveEverything = true; CarbonClient cbnClient = DataHandler.GetCarbonClient(); try { int nBonds = BondId.GetLength(0); // Holidays can be given as holiday code (string) or as array of dates. // Get Bond static data #region Bond Static Data object o = null; DateTime[] maturity = new DateTime[nBonds], effectiveDate = new DateTime[nBonds], firstCpnDate = new DateTime[nBonds]; double[] coupon = new double[nBonds]; bool bEUR = false; long bondCpnFreq = 6; BondAnalytics.Country eCountry = BondAnalytics.Country.US, prevCountry = BondAnalytics.Country.US; for (int i = 0; i < nBonds; i++) { var lid = ((String) BondId[i]).Trim().ToLower(); BondStatic bndStatic = DataHandler.GetBondStatic(lid); maturity[i] = DateTime.FromOADate(bndStatic.Maturity); effectiveDate[i] = DateTime.FromOADate(bndStatic.EffectiveDate); firstCpnDate[i] = DateTime.FromOADate(bndStatic.FirstCoupon); coupon[i] = bndStatic.Coupon; BondAnalytics.CountryMappings.TryGetValue(((String) BondId[i]).Substring(0, 2), out eCountry); if (i > 0 && eCountry != prevCountry) { throw new ArgumentException("#Error! All bonds must be same country!"); } prevCountry = eCountry; } // Let's use spreadseries config string sCountry = ((String) BondId[0]).Substring(0, 2); // since all countries are the same var fcstConfig = new SpreadTimeSeriesConfigs(sCountry, bForecastCurve: true); var discConfig = new SpreadTimeSeriesConfigs(sCountry, bForecastCurve: false); bEUR = (eCountry == BondAnalytics.Country.DE || eCountry == BondAnalytics.Country.FR || eCountry == BondAnalytics.Country.IT || eCountry == BondAnalytics.Country.ES || eCountry == BondAnalytics.Country.BE ? true : false); bondCpnFreq = fcstConfig.bndCouponFreq; //(eCountry == BondAnalytics.Country.US || eCountry == BondAnalytics.Country.UK || eCountry == BondAnalytics.Country.JP || eCountry == BondAnalytics.Country.CA ? 6 : 12); #endregion // Build timeseries calendar #region DateSeries List<DateTime> dateSeries = new List<DateTime>(); // Ensure start and end date are good business days. Move dates forward then back to minimise chance of future dates in series. DateTime startDate = StartDate.AddTenor(Tenor.FromString("1b"), "") .AddTenor(Tenor.FromString("-1b"), ""); DateTime nextDate = EndDate.AddTenor(Tenor.FromString("1b"), "").AddTenor(Tenor.FromString("-1b"), ""); if (startDate > nextDate) { throw new ArgumentException("nextDate must be after start date"); } var tenor = Tenor.FromString("-" + TenorString); while (nextDate >= startDate) { dateSeries.Add(nextDate); nextDate = BondAnalytics.PrevBusDay(nextDate.AddTenor(tenor, ""), Holidays); } int M = dateSeries.Count(); // Keep a track of pricing errors so that a failure for one bond / date does not have to cause a failure of the whole function. Boolean[,] bPricingCheck = new Boolean[M, nBonds]; #endregion // Need discount curve before calculating repo series. #region InterestCurves String discCurveName = discConfig.SymDiscountCurveName; String fcstCurveName = fcstConfig.SymForecastCurveName; String ccy = fcstConfig.ccy; // Convert DiscountCurve Object to tuples. var DiscCurves = new SortedDictionary<DateTime, Tuple<DateTime, double>[]>(); var FcstCurves = new SortedDictionary<DateTime, Tuple<DateTime, double>[]>(); // DISC. SortedDictionary<DateTime, DiscountCurve> DiscCurvesRaw = DataHandler.getDiscountCurvesInDateRange(discCurveName, dateSeries); foreach (var dte in DiscCurvesRaw.Keys) { DiscCurves[dte] = DiscCurvesRaw[dte].AsTuples(); } // FCST. if (!bOIS && (Measure != "Repo" && Measure != "Yield" && Measure != "Price")) // only get fcst curves here { SortedDictionary<DateTime, DiscountCurve> FcstCurvesRaw = DataHandler.getDiscountCurvesInDateRange(fcstCurveName, dateSeries); foreach (var dte in FcstCurvesRaw.Keys) { FcstCurves[dte] = FcstCurvesRaw[dte].AsTuples(); } } #endregion InterestCurves // Get repo spread. Three cases: default is 20 day moving average of GC-OIS, alternatives are input flat rate or interpolation from input table. #region RepoHistory double[,] fwdPrices = new double[M, nBonds]; double[,] repoSpread = new double[M, nBonds]; // Two column array - dates / spreads. Linear interpolation in date. if ((SpreadOrPrice.GetLength(1) == 2 || SpreadOrPrice.GetLength(1) == nBonds + 1) && SpreadOrPrice.GetLength(0) > 1) { int nRepos = SpreadOrPrice.GetLength(0); int nCols = SpreadOrPrice.GetLength(1); DateTime[] rDates = new DateTime[nRepos]; double[,] rSpreads = new double[nRepos, nBonds]; for (int j = 0; j < nBonds; j++) { for (int i = 0; i < nRepos; i++) { if (SpreadOrPrice[i, 0] is double) { rDates[i] = DateTime.FromOADate((double)SpreadOrPrice[i, 0]).Date; if (nCols > 1 + j && SpreadOrPrice[i, 1 + j] is double) rSpreads[i, j] = (double)SpreadOrPrice[i, 1 + j]; else if (1 + j >= nCols) { rSpreads[i, j] = rSpreads[i, j - 1]; } else { // Spread override is not a double, pricing fails. Use -1e8 as an error warning. rSpreads[i, j] = -1e8; } } else { rDates[i] = DateTime.MinValue; } } } // Not very efficient, but need to identify matching dates when not necessarily in order because of input errors. if (bSpread) { int k; for (int i = 0; i < M; i++) { for (k = 0; k < nRepos; k++) { if (rDates[k].Date == dateSeries[i].Date) { for (int j = 0; j < nBonds; j++) { if (rSpreads[i, j] < -1e7) bPricingCheck[i, j] = true; else repoSpread[i, j] = rSpreads[i, j] / 10000.0; } break; } } if (k == nRepos) { for (int j = 0; j < nBonds; j++) { bPricingCheck[i, j] = true; } } } } else { int k; for (int i = 0; i < M; i++) { for (k = 0; k < nRepos; k++) { if (rDates[k].Date == dateSeries[i].Date) { for (int j = 0; j < nBonds; j++) { if (rSpreads[i, j] < -1e7) bPricingCheck[i, j] = true; else fwdPrices[i, j] = rSpreads[i, j]; } break; } } if (k == nRepos) { for (int j = 0; j < nBonds; j++) { bPricingCheck[i, j] = true; } } } } } // Cases: Single entry, double then this is the flat spread. else if (SpreadOrPrice.GetLength(0) == 1 && SpreadOrPrice.GetLength(1) == 1 && SpreadOrPrice[0, 0] is double) { if (bSpread) { for (int j = 0; j < nBonds; j++) { for (int i = 0; i < M; i++) { repoSpread[i, j] = (double)SpreadOrPrice[0, 0] / 10000.0; } } } else { for (int j = 0; j < nBonds; j++) { for (int i = 0; i < M; i++) { fwdPrices[i, j] = (double)SpreadOrPrice[0, 0]; } } } } // Vector, length nBonds else if (((SpreadOrPrice.GetLength(0) == nBonds && SpreadOrPrice.GetLength(1) == 1) || (SpreadOrPrice.GetLength(1) == nBonds && SpreadOrPrice.GetLength(0) == 1)) && SpreadOrPrice[0, 0] is double) { bool bRow = SpreadOrPrice.GetLength(1) == 1; if (bSpread) { for (int j = 0; j < nBonds; j++) { for (int i = 0; i < M; i++) repoSpread[i, j] = (double)(bRow ? SpreadOrPrice[j, 0] : SpreadOrPrice[0, j]) / 10000.0; } } else { for (int j = 0; j < nBonds; j++) { for (int i = 0; i < M; i++) fwdPrices[i, j] = (double)(bRow ? SpreadOrPrice[j, 0] : SpreadOrPrice[0, j]); } } } // Otherwise (empty, or not a double or a two column array). else { bSpread = true; // Repo spread is 20 day moving average of GC - OIS double[] gcHist = new double[M + 19]; double[] oisHist = new double[M + 19]; var opGC = DataHandler.GetRepoRates(eCountry, dateSeries); for (int i = 0; i < M; i++) { // Copy GC values over (we need to extend this later) gcHist[i] = opGC[i]; if (DiscCurves.ContainsKey(dateSeries[i])) { oisHist[i] = Math.Round((1.0 / DiscCurves[dateSeries[i]].ElementAt(1).Item2 - 1.0) * 360.0 / (DiscCurves[dateSeries[i]].ElementAt(1).Item1 - DiscCurves[dateSeries[i]].ElementAt(0).Item1).TotalDays, 5); } else { bHaveEverything = false; } } // Dates prior to dateSeries[0] List<DateTime> prevDates = new List<DateTime>(); for (int i = 0; i < 19; i++) { prevDates.Add(BondAnalytics.PrevBusDay((i == 0 ? dateSeries[M - 1] : prevDates.Last()).AddDays(-1), Holidays)); } // Get old curves var PrevDiscCurves = new SortedDictionary<DateTime, Tuple<DateTime, double>[]>(); var prevDiscCurvesRaw = DataHandler.getDiscountCurvesInDateRange(discCurveName, prevDates); foreach (var kvp in prevDiscCurvesRaw) { PrevDiscCurves[kvp.Key] = kvp.Value.AsTuples(); } // Get old rates double[] oldRepoRates = DataHandler.GetRepoRates(eCountry, prevDates); for (int i = 0; i < 19; i++) { o = oldRepoRates[i]; if (o is double) { gcHist[M + i] = (double)o / 100.0; } else if (i > 0) { gcHist[M + i] = gcHist[M + i]; } else gcHist[M + i] = 0.0; if (PrevDiscCurves.ContainsKey(prevDates[i])) { oisHist[M + i] = Math.Round((1.0 / PrevDiscCurves[prevDates[i]].ElementAt(1).Item2 - 1.0) * 360.0 / (PrevDiscCurves[prevDates[i]].ElementAt(1).Item1 - PrevDiscCurves[prevDates[i]].ElementAt(0).Item1).TotalDays, 5); } else { bHaveEverything = false; } } for (int i = 0; i < M; i++) { for (int j = i; j < i + 20; j++) { repoSpread[i, 0] += (gcHist[j] - oisHist[j]) / 20.0; } } for (int i = 0; i < M; i++) for (int j = 1; j < nBonds; j++) repoSpread[i, j] = repoSpread[i, 0]; } #endregion // Get Price Data (Clean Prices, Repo rates - i.e. term OIS rates + repo spreads) #region GetPricingData List<double[]> priceSeries = new List<double[]>(); List<double[]> repoSeries = new List<double[]>(); // Let's get price data from symmetry service if (bSpread) { for (int i = 0; i < M; i++) { priceSeries.Add(new double[nBonds]); repoSeries.Add(new double[nBonds]); DateTime settleDate = BondAnalytics.NextBusDay(dateSeries[i].Date.AddDays(1), Holidays); if (eCountry != BondAnalytics.Country.US) { settleDate = BondAnalytics.NextBusDay(dateSeries[i].Date.AddDays(2), Holidays); } for (int j = 0; j < nBonds; j++) { if (settleDate.Date > FwdDate.Date) { bPricingCheck[i, j] = true; continue; } var priceMonikerName = ((String)BondId[j]).ToLower().Trim(); var priceMonikerDate = dateSeries[i]; var closeTup = DataHandler.GetCloseSnap(priceMonikerDate, eCountry); var priceMonikerClose = closeTup.Item1; var priceMonikerSource = closeTup.Item2; try { o = DataHandler.GetHistoryPrice(priceMonikerName, priceMonikerDate, priceMonikerClose, priceMonikerSource); } catch { } if (o is double) priceSeries[i][j] = (double)o; else if (dateSeries[i].Date < effectiveDate[j].Date || !DiscCurves.ContainsKey(dateSeries[i])) { // No price information available bPricingCheck[i, j] = true; } else bHaveEverything = false; } double oisSwap = 0.0; if (DiscCurves.ContainsKey(dateSeries[i])) { DateTime[] discDfDates = DiscCurves[dateSeries[i]].Select(x => x.Item1).ToArray(); double[] discDfs = DiscCurves[dateSeries[i]].Select(x => x.Item2).ToArray(); oisSwap = settleDate.Date < FwdDate.Date ? BondAnalytics.CalcMMS(settleDate, FwdDate, BondAnalytics.DayCountType.Act360, 12, 12, discDfDates, discDfs, discDfDates, discDfs, Holidays, null, null, null, null, null, DateTime.MinValue, 5) : 0.0; } for (int j = 0; j < nBonds; j++) { repoSeries[i][j] = oisSwap + repoSpread[i, j]; } } } #endregion // Calculate measures #region CalcMeasures List<double[]> outputSeries = new List<double[]>(); for (int i = 0; i < M; i++) { outputSeries.Add(new double[nBonds + (Measure == "Repo" ? 1 : 0)]); DateTime settleDate = BondAnalytics.NextBusDay(dateSeries[i].Date.AddDays(1), Holidays); if (eCountry != BondAnalytics.Country.US) { settleDate = BondAnalytics.NextBusDay(dateSeries[i].Date.AddDays(2), Holidays); } for (int j = 0; j < nBonds; j++) { // Only attempt to price if there is a chance of success! if (bPricingCheck[i, j]) continue; double fwdPrice = bSpread ? BondAnalytics.CalcBondFwd(eCountry, settleDate, priceSeries[i][j], effectiveDate[j], firstCpnDate[j], maturity[j], coupon[j], bondCpnFreq, FwdDate, repoSeries[i][j])[0] : fwdPrices[i, j]; switch (Measure) { case "Price": { outputSeries[i][j] = fwdPrice; break; } case "Yield": { outputSeries[i][j] = 10000.0 * BondAnalytics.SolveYield(eCountry, FwdDate, fwdPrice, effectiveDate[j], firstCpnDate[j], maturity[j], coupon[j], bondCpnFreq)[0]; break; } case "TrueSpread": { if ((bOIS && DiscCurves.ContainsKey(dateSeries[i])) || FcstCurves.ContainsKey(dateSeries[i])) { DateTime[] dfDates = (bOIS ? DiscCurves[dateSeries[i]].Select(x => x.Item1).ToArray() : FcstCurves[dateSeries[i]].Select(x => x.Item1).ToArray()); double[] dfs = (bOIS ? DiscCurves[dateSeries[i]].Select(x => x.Item2).ToArray() : FcstCurves[dateSeries[i]].Select(x => x.Item2).ToArray()); // Check. Sometimes (holidays) the first date on the curve can be repeated, which will cause an exception in the pricer. if (dfDates[0] == dfDates[1]) { dfDates = dfDates.GetSubArray(1, dfDates.GetLength(0)).ToArray(); dfs = dfs.GetSubArray(1, dfs.GetLength(0)).ToArray(); } outputSeries[i][j] = -10000.0 * BondAnalytics.SolveZSpread(eCountry, FwdDate, fwdPrice, effectiveDate[j], firstCpnDate[j], maturity[j], coupon[j], bondCpnFreq, dfDates, dfs, Holidays); } else { bPricingCheck[i, j] = true; } break; } case "MMS": { if (DiscCurves.ContainsKey(dateSeries[i]) && (bOIS || FcstCurves.ContainsKey(dateSeries[i]))) { DateTime[] discDfDates = DiscCurves[dateSeries[i]].Select(x => x.Item1).ToArray(); DateTime[] fcstDfDates = (bOIS ? discDfDates : FcstCurves[dateSeries[i]].Select(x => x.Item1).ToArray()); double[] discDfs = DiscCurves[dateSeries[i]].Select(x => x.Item2).ToArray(); double[] fcstDfs = (bOIS ? discDfs : FcstCurves[dateSeries[i]].Select(x => x.Item2).ToArray()); BondAnalytics.DayCountType dct = (bOIS ? BondAnalytics.DayCountType.Act360 : BondAnalytics.DayCountType.E30360); int fixedFreq = (bEUR || bOIS ? 12 : 6); int floatFreq = (bOIS ? 12 : (bEUR ? 6 : 3)); double mms = BondAnalytics.CalcMMS(FwdDate, maturity[j], dct, fixedFreq, floatFreq, discDfDates, discDfs, fcstDfDates, fcstDfs, Holidays, null, null, null, null, null, firstCpnDate[j], (bOIS ? 5 : 0)); outputSeries[i][j] = 10000.0 * mms; } else { bPricingCheck[i, j] = true; } break; } case "Spread": { if (DiscCurves.ContainsKey(dateSeries[i]) && (bOIS || FcstCurves.ContainsKey(dateSeries[i]))) { DateTime[] discDfDates = DiscCurves[dateSeries[i]].Select(x => x.Item1).ToArray(); DateTime[] fcstDfDates = (bOIS ? discDfDates : FcstCurves[dateSeries[i]].Select(x => x.Item1).ToArray()); double[] discDfs = DiscCurves[dateSeries[i]].Select(x => x.Item2).ToArray(); double[] fcstDfs = (bOIS ? discDfs : FcstCurves[dateSeries[i]].Select(x => x.Item2).ToArray()); BondAnalytics.DayCountType dct = (bOIS ? BondAnalytics.DayCountType.Act360 : BondAnalytics.DayCountType.E30360); int fixedFreq = (bEUR || bOIS ? 12 : 6); int floatFreq = (bOIS ? 12 : (bEUR ? 6 : 3)); double mms = BondAnalytics.CalcMMS(FwdDate, maturity[j], dct, fixedFreq, floatFreq, discDfDates, discDfs, fcstDfDates, fcstDfs, Holidays, null, null, null, null, null, firstCpnDate[j], (bOIS ? 5 : 0)); double yield = BondAnalytics.SolveYield(eCountry, FwdDate, fwdPrice, effectiveDate[j], firstCpnDate[j], maturity[j], coupon[j], bondCpnFreq)[0]; outputSeries[i][j] = 10000.0 * (mms - yield); } else { bPricingCheck[i, j] = true; } break; } case "Repo": { if (bSpread) { outputSeries[i][j] = 10000 * repoSpread[i, j]; if (j == 0) outputSeries[i][nBonds] = 10000 * (repoSeries[i][0] - repoSpread[i, 0]); } break; } } } } #endregion Dictionary<DateTime, Series<string,double>> output = new Dictionary<DateTime, Series<string, double>>(); for (int i = 0; i < M; i++) { SeriesBuilder<string, double> sb = new SeriesBuilder<string, double>(); for (int j = 0; j < nBonds + (Measure == "Repo" ? 1 : 0); j++) { if (j < nBonds && bPricingCheck[i, j]) { sb.Add(BondId[j], double.NaN); } else { if (j >= nBonds) { sb.Add("Repo", outputSeries[i][j]); } else { sb.Add(BondId[j], outputSeries[i][j]); } } } output[dateSeries[i].Date] = sb.Series; } var result = Frame.FromRows(output); return result; } catch (Exception ex) { Log_.ErrorFormat("Error in BondASWCalc: {0}", ex.Message); throw ex; } }