【问题标题】:C# LINQ Z-Score query output to a Dictionary<string, SortedList<DateTime, double>>C# LINQ Z-Score 查询输出到 Dictionary<string, SortedList<DateTime, double>>
【发布时间】:2011-03-29 10:13:27
【问题描述】:

我编写了一个查询,对给定日期的所有值执行 Z 分数计算。计算似乎很好,但我无法将此查询的结果转换为函数可以返回的格式。 Z-scores 以 {symbol, date, z-score} 的格式放入List&lt;object&gt;。问题实际上是如何将 List&lt;object&gt; 转换为我需要的格式。

我希望它返回一个Dictionary&lt;string, SortedList&lt;DateTime, double&gt;&gt;,它由安全字符串和一个排序列表组成,其中包含该安全的所有日期和z-score 值对。

即。 Dictionary&lt;security, SortedList&lt;Dates, Z-Scores&gt;&gt;

查询计算是正确的(我认为 ;->),但任何关于改进查询的建议也将不胜感激,因为我仍然是一个 LINQ 挑战者!

这是一个示例实现:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Ranking_Query
{
    class Program
    {
        static void Main(string[] args)
        {
            // created an instance of the datasource and add 4 securities and their time-series to it
            Datasource ds = new Datasource() { Name = "test" };

            ds.securities.Add("6752 JT", new Security()
            {
                timeSeries = new Dictionary<string, SortedList<DateTime, double>>() {
                        { "Mkt_Cap", new SortedList<DateTime, double>() { 
                            {new DateTime(2011,01,16),300},
                            {new DateTime(2011,01,17),303},
                            {new DateTime(2011,01,18),306},
                            {new DateTime(2011,01,19),309} } } ,
                        { "Liquidity_Rank", new SortedList<DateTime, double>() { 
                            {new DateTime(2011,01,16),1},
                            {new DateTime(2011,01,17),2},
                            {new DateTime(2011,01,18),3},
                            {new DateTime(2011,01,19),4} } }
                }
            });

            ds.securities.Add("6753 JT", new Security()
            {
                timeSeries = new Dictionary<string, SortedList<DateTime, double>>() {
                        { "Mkt_Cap", new SortedList<DateTime, double>() { 
                            {new DateTime(2011,01,16),251},
                            {new DateTime(2011,01,17),252},
                            {new DateTime(2011,01,18),253}, 
                            {new DateTime(2011,01,19),254} } } ,
                        { "Liquidity_Rank", new SortedList<DateTime, double>() { 
                            {new DateTime(2011,01,16),2},
                            {new DateTime(2011,01,17),3},
                            {new DateTime(2011,01,18),4},
                            {new DateTime(2011,01,19),1} } }
                }
            });

            ds.securities.Add("6754 JT", new Security()
            {
                timeSeries = new Dictionary<string, SortedList<DateTime, double>>() {
                        { "Mkt_Cap", new SortedList<DateTime, double>() { 
                            {new DateTime(2011,01,16),203},
                            {new DateTime(2011,01,17),205},
                            {new DateTime(2011,01,18),207},
                            {new DateTime(2011,01,19),209}  } },
                        { "Liquidity_Rank", new SortedList<DateTime, double>() { 
                            {new DateTime(2011,01,16),3},
                            {new DateTime(2011,01,17),4},
                            {new DateTime(2011,01,18),1},
                            {new DateTime(2011,01,19),2} } }
                }
            });

            ds.securities.Add("6755 JT", new Security()
            {
                timeSeries = new Dictionary<string, SortedList<DateTime, double>>() {
                        { "Mkt_Cap", new SortedList<DateTime, double>() { 
                            {new DateTime(2011,01,16),100},
                            {new DateTime(2011,01,17),101},
                            {new DateTime(2011,01,18),103},
                            {new DateTime(2011,01,19),104} } },
                        { "Liquidity_Rank", new SortedList<DateTime, double>() { 
                            {new DateTime(2011,01,16),4},
                            {new DateTime(2011,01,17),1},
                            {new DateTime(2011,01,18),2},
                            {new DateTime(2011,01,19),3} } }
                }
            });

            // set minimum liquidty rank
            int MinLiqRank = 2;

            // Initial query to get a sequence of { Symbol, Date, Mkt_Cap } entries that meet minimum liquidty rank.
            var entries = from securityPair in ds.securities
                          from valuation_liq in securityPair.Value.timeSeries["Liquidity_Rank"]
                          from valuation_MC in securityPair.Value.timeSeries["Mkt_Cap"]
                          where (valuation_liq.Key == valuation_MC.Key) && (valuation_liq.Value >= MinLiqRank)
                          select new
                          {
                              Symbol = securityPair.Key,
                              Date = valuation_liq.Key,
                              MktCap = valuation_MC.Value
                          };      


            // Now group by date 
            var groupedByDate = from entry in entries
                                group entry by entry.Date into date
                                select date.OrderByDescending(x => x.MktCap)
                                           .ThenBy(x => x.Symbol)
                                           .Select(x  => new
                                           {
                                               x.Symbol,
                                               x.MktCap,
                                               x.Date
                                           });


            // final results should populate the following Dictionary of symbols and their respective Z-score time series
            var zScoreResult = new Dictionary<string, SortedList<DateTime, double>>();

            // Calculate the Z-scores for each day
            bool useSampleStdDev = true;
            var results = new List<object>();
            foreach (var sec in groupedByDate)
            {
                // calculate the average value for the date
                double total = 0;
                foreach (var secRank in sec)
                    total += secRank.MktCap;
                double avg = total/ sec.Count();


                // calculate the standard deviation
                double SumOfSquaredDev = 0;
                foreach (var secRank in sec)
                    SumOfSquaredDev += ((secRank.MktCap - avg) * (secRank.MktCap - avg));

                double stdDev;
                if (useSampleStdDev)
                    // sample standard deviation 
                    stdDev = Math.Sqrt(SumOfSquaredDev / (sec.Count() - 1));                    
                else
                    // population standard deviation
                    stdDev = Math.Sqrt(SumOfSquaredDev / sec.Count());


                Console.WriteLine("{0} AvgMktCap {1}, StdDev {2}", sec.First().Date, Math.Round(avg,2), Math.Round(stdDev,2));

                // calculate the Z-score
                double zScore;
                foreach (var secRank in sec)
                {
                    zScore = ((secRank.MktCap - avg) / stdDev);
                    results.Add(new { Symbol = secRank.Symbol, Date = sec.First().Date, zScore = zScore });
                    Console.WriteLine("  {0} MktCap {1} Z-Score {2}", secRank.Symbol, secRank.MktCap, Math.Round(zScore, 2));
                }                
            }


        }

        class Datasource
        {
            public string Name { get; set; }
            public Dictionary<string, Security> securities = new Dictionary<string, Security>();
        }

        class Security
        {
            public string symbol { get; set; }
            public Dictionary<string, SortedList<DateTime, double>> timeSeries;
        }

    }
}

任何帮助将不胜感激。

【问题讨论】:

    标签: c# linq dictionary


    【解决方案1】:

    这个问题没有得到正确的关注,并且有太多的代码和不必要的细节。所以它没有得到答复。我把它剪掉并重新发布。查看对转发的回复有两点变得清晰。

    1. 我真的在问如何拆箱匿名类型。提供了装箱/拆箱的解决方案 here
    2. 使用匿名类型是个坏主意。建议为返回类型定义一个类。

    经过思考,我突然想到我可以跳过整个问题,只需将结果以我想要的形式从一开始就插入字典中,因为我通过计算分数来迭代...... d'Uh!

    我修改了以下代码:

    results.Add(new { Symbol = secRank.Symbol, Date = sec.First().Date, zScore = zScore });
    

    阅读:

    if (!results.ContainsKey(secRank.Symbol))
       results.Add(secRank.Symbol,new SortedList<DateTime,double>()); 
    
    results[secRank.Symbol].Add(sec.First().Date, zScore); 
    

    并更改了结果的定义

    var results = new List<object>();
    

    var results = new Dictionary<string, SortedList<DateTime, double>>();
    

    我从这一切中学到了什么?那些没有得到解答的问题可能是经过深思熟虑的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-01
      • 2011-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多