public void Create(ConstructGen<double> wts_, FXGroup[] groups_)
    {
      ConstructGen<double> groupConv = new ConstructGen<double>(groups_.Length);
      groupConv.ColumnHeadings = groups_.Select(x => x.ToString()).ToArray();
      Currency[] ccys = wts_.ColumnHeadings.Select(x => Singleton<FXIDs>.Instance[x]).ToArray();

      List<int[]> indicies =new List<int[]>();

      foreach(FXGroup group in groups_)
      {
        List<int> groupIndicies=new List<int>();
        for(int i=0;i<ccys.Length;++i)
          if(ccys[i].IsGroup(group))
            groupIndicies.Add(i);
        
        indicies.Add(groupIndicies.ToArray());
      }

      foreach (DateTime date in wts_.Dates)
      {
        double[] dateWeights = wts_.GetValues(date);
        double[] buckets = new double[groups_.Length];

        for(int g=0;g<groups_.Length;++g)
          foreach (int index in indicies[g])
            buckets[g] += dateWeights[index];

        groupConv.SetValues(date, buckets);
      }

      DataTable dt1 = groupConv.ToDataTable(groupConv.ColumnHeadings, "Date", "dd-MMM-yyyy");

      Chart.ChartType = Infragistics.UltraChart.Shared.Styles.ChartType.Composite;

      ChartArea area = new ChartArea();
      Chart.CompositeChart.ChartAreas.Add(area);

      AxisItem axisY = new AxisItem();
      axisY.Extent = 50;
      axisY.DataType = AxisDataType.Numeric;
      axisY.OrientationType = AxisNumber.Y_Axis;
      axisY.LineColor = Color.Blue;
      axisY.Labels.Visible = true;
      area.Axes.Add(axisY);

      AxisItem axisX = new AxisItem();
      axisX.DataType = AxisDataType.String;
      axisX.Extent = 80;
      axisX.SetLabelAxisType = Infragistics.UltraChart.Core.Layers.SetLabelAxisType.GroupBySeries;
      axisX.OrientationType = AxisNumber.X_Axis;
      axisX.LineColor = Color.Blue;
      axisX.Labels.Orientation = TextOrientation.VerticalLeftFacing;
      axisX.Labels.SeriesLabels.Orientation = TextOrientation.VerticalLeftFacing;
      area.Axes.Add(axisX);

      AxisItem axisX2 = new AxisItem();
      axisX2.DataType = AxisDataType.String;
      axisX2.Extent = 80;
      axisX2.OrientationType = AxisNumber.X_Axis;
      axisX2.LineColor = Color.Blue;
      axisX2.Labels.Orientation = TextOrientation.VerticalLeftFacing;
      axisX2.Labels.SeriesLabels.Orientation = TextOrientation.VerticalLeftFacing;
      axisX2.SetLabelAxisType = SetLabelAxisType.ContinuousData;
      area.Axes.Add(axisX2);

      ChartLayerAppearance myColumnLayer = new ChartLayerAppearance();
      myColumnLayer.ChartType = ChartType.StackColumnChart;
      myColumnLayer.ChartArea = area;

      foreach (FXGroup group in groups_)
      {
        NumericSeries series1 = new NumericSeries();
        series1.Key = group.ToString();
        series1.DataBind(dt1, group.ToString(), "Date");
        series1.PEs.Add(new PaintElement(ColorAttribute.GetAttribute(group).Color));
        myColumnLayer.Series.Add(series1);
        Chart.CompositeChart.Series.Add(series1);
      }

      DataTable dt2 = wts_.SumRows().ToDataTable(format_:"dd-MMM-yyyy");

      ChartLayerAppearance myColumnLayer2 = new ChartLayerAppearance();
      myColumnLayer2.ChartType = ChartType.LineChart;
      myColumnLayer2.ChartArea = area;

      NumericSeries seriesA = new NumericSeries();
      seriesA.Key = "Sum of Wts";
      seriesA.DataBind(dt2, "Value", "Date");
      seriesA.PEs.Add(new PaintElement(Color.Orange));
      myColumnLayer2.Series.Add(seriesA);
      Chart.CompositeChart.Series.Add(seriesA);


      LineChartAppearance la = new LineChartAppearance();
      la.Thickness = 4;
      myColumnLayer2.ChartTypeAppearance = la;


      myColumnLayer.AxisX = axisX;
      myColumnLayer.AxisY = axisY;

      myColumnLayer2.AxisX = axisX2;
      myColumnLayer2.AxisY = axisY;

      myColumnLayer.SwapRowsAndColumns = true;
      this.Chart.CompositeChart.ChartLayers.Add(myColumnLayer);
      this.Chart.CompositeChart.ChartLayers.Add(myColumnLayer2);

      EstablishDefaultTooltip();
      m_wts = wts_;
      m_groups = groups_;
      pbSplitIntoYears.BringToFront();
    }
    public static void Test()
    {
      const int lookback = 5;
      const WeightGeneratorType genType = WeightGeneratorType.LongestZScoreOverThreshold;

      SpreadWeightGenerator[] arr = new[]
      {
        new SpreadWeightGenerator(
          new WeightGeneratorArgs()
          {
            Lookback = lookback,
            WeightGenerationType = genType,
            MinWindowLength = 50,
            ZScoreThreshold = 1.3d
          },
          new SpreadDefinition(
            new MonthYearOffset(ComIDs.Sugar, 0, MonthCode.V),
            new MonthYearOffset(ComIDs.Sugar, 1, MonthCode.K),
            false)),
        //new SpreadWeightGenerator(
        //  new WeightGeneratorArgs()
        //  {
        //    Lookback = lookback,
        //    WeightGenerationType = genType,
        //    MinWindowLength = 40,
        //    ZScoreThreshold = 1d
        //  },
        //  new SpreadDefinition(
        //    new MonthYearOffset(ComIDs.Sugar, 0, MonthCode.V),
        //    new MonthYearOffset(ComIDs.Sugar, 1, MonthCode.K),
        //    false)),
        //new SpreadWeightGenerator(
        //  new WeightGeneratorArgs()
        //  {
        //    Lookback = lookback,
        //    WeightGenerationType = genType,
        //    MinWindowLength = 40,
        //    ZScoreThreshold = 1.5d
        //  },
        //  new SpreadDefinition(
        //    new MonthYearOffset(ComIDs.NatGas, 0, MonthCode.H),
        //    new MonthYearOffset(ComIDs.NatGas, 0, MonthCode.X),
        //    false)),
        new SpreadWeightGenerator(
          new WeightGeneratorArgs()
          {
            Lookback = lookback,
            WeightGenerationType = genType,
            MinWindowLength = 60,
            ZScoreThreshold = 1.2d
          },
          new SpreadDefinition(
            new MonthYearOffset(ComIDs.NymexGas, 0, MonthCode.H),
            new MonthYearOffset(ComIDs.NymexGas, 0, MonthCode.X),
            false)),
        //new SpreadWeightGenerator(
        //  new WeightGeneratorArgs()
        //  {
        //    Lookback = lookback,
        //    WeightGenerationType = genType,
        //    MinWindowLength = 90,
        //    ZScoreThreshold = 1.7d
        //  },
        //  new SpreadDefinition(
        //    new MonthYearOffset(ComIDs.NatGas, 0, MonthCode.H),
        //    new MonthYearOffset(ComIDs.NatGas, 0, MonthCode.X),
        //    false)),
        //new SpreadWeightGenerator(
        //  new WeightGeneratorArgs()
        //  {
        //    Lookback = lookback,
        //    WeightGenerationType = genType,
        //    MinWindowLength = 40,
        //    ZScoreThreshold = 1.6d
        //  },
        //  new SpreadDefinition(
        //    new MonthYearOffset(ComIDs.Corn, 0, MonthCode.U),
        //    new MonthYearOffset(ComIDs.Corn, 0, MonthCode.Z),
        //    false)),
        new SpreadWeightGenerator(
          new WeightGeneratorArgs()
          {
            Lookback = lookback,
            WeightGenerationType = genType,
            MinWindowLength = 60,
            ZScoreThreshold = 1.3d
          },
          new SpreadDefinition(
            new MonthYearOffset(ComIDs.Corn, 0, MonthCode.U),
            new MonthYearOffset(ComIDs.Corn, 0, MonthCode.Z),
            false)),
        //new SpreadWeightGenerator(
        //  new WeightGeneratorArgs()
        //  {
        //    Lookback = lookback,
        //    WeightGenerationType = genType,
        //    MinWindowLength = 90,
        //    ZScoreThreshold = 0.8d
        //  },
        //  new SpreadDefinition(
        //    new MonthYearOffset(ComIDs.Corn, 0, MonthCode.U),
        //    new MonthYearOffset(ComIDs.Corn, 0, MonthCode.Z),
        //    false)),
        new SpreadWeightGenerator(
          new WeightGeneratorArgs()
          {
            Lookback = lookback,
            WeightGenerationType = genType,
            MinWindowLength = 40,
            ZScoreThreshold = 1.5d
          },
          new SpreadDefinition(
            new MonthYearOffset(ComIDs.Wheat, 0, MonthCode.U),
            new MonthYearOffset(ComIDs.Wheat, 0, MonthCode.Z),
            false)),
        //new SpreadWeightGenerator(
        //  new WeightGeneratorArgs()
        //  {
        //    Lookback = lookback,
        //    WeightGenerationType = genType,
        //    MinWindowLength = 50,
        //    ZScoreThreshold = 1.3d
        //  },
        //  new SpreadDefinition(
        //    new MonthYearOffset(ComIDs.Wheat, 0, MonthCode.U),
        //    new MonthYearOffset(ComIDs.Wheat, 0, MonthCode.Z),
        //    false)),
        //new SpreadWeightGenerator(
        //  new WeightGeneratorArgs()
        //  {
        //    Lookback = lookback,
        //    WeightGenerationType = genType,
        //    MinWindowLength = 70,
        //    ZScoreThreshold = 1.1d
        //  },
        //  new SpreadDefinition(
        //    new MonthYearOffset(ComIDs.Wheat, 0, MonthCode.U),
        //    new MonthYearOffset(ComIDs.Wheat, 0, MonthCode.Z),
        //    false)),
        new SpreadWeightGenerator(
          new WeightGeneratorArgs()
          {
            Lookback = lookback,
            WeightGenerationType = genType,
            MinWindowLength = 50,
            ZScoreThreshold = 1.6d
          },
          new SpreadDefinition(
            new MonthYearOffset(ComIDs.RBOB, 0, MonthCode.J),
            new MonthYearOffset(ComIDs.RBOB, 0, MonthCode.U),
            false)),
      };

      var comb = new SpreadWeightGeneratorCombiner(arr) {NumDaysForCovariance = 42, TargetVol = 0.06};
      comb.Go();

      {
        var combinedPnl = new ConstructGen<double>(arr.Length);

        combinedPnl.ColumnHeadings =
          arr.Select(x => string.Format("{0} / {1} / {2}", x.Spread, x.Args.MinWindowLength, x.Args.ZScoreThreshold))
            .ToArray();

        for (int i = 0; i < arr.Length; ++i)
          combinedPnl.SetColumnValues(i, arr[i].GetCombinedPnl());

        if (combinedPnl.NeedsToSortKeys())
          combinedPnl.SortKeys();


        var eval = new ReturnsEval.DataSeriesEvaluator("Combined", ReturnsEval.DataSeriesType.Returns);
        eval.AddInnerSeries(combinedPnl.Dates.ToArray(), combinedPnl.ToArray(), combinedPnl.ColumnHeadings);
        eval.Display("Combined");

        combinedPnl.SumRows().ToCumulative().DisplayLineChart("combined pnl of scaled weights");
      }

    }
Esempio n. 3
0
    public ChartData GetData()
    {
      var enabled = Components.Where(x => x.IsReady()).ToList();

      if (!enabled.Any())
        return null;


      DateTime[] oldDates, rollDates;
        DatedDataCollectionGen<double> primary, old, oldold, ooo, oooo, smthd, oldsmthd, oosmthd, ooosmthd;
      {
        ConstructGen<double> con = new ConstructGen<double>(enabled.Count());
        ConstructGen<double> conOld = new ConstructGen<double>(enabled.Count());
        ConstructGen<double> conOldOld = new ConstructGen<double>(enabled.Count());
        ConstructGen<double> conOOO = new ConstructGen<double>(enabled.Count());
        ConstructGen<double> conOOOO = new ConstructGen<double>(enabled.Count());
        ConstructGen<double> conSmoothed = new ConstructGen<double>(enabled.Count());
        ConstructGen<double> conOldSmoothed = new ConstructGen<double>(enabled.Count());
        ConstructGen<double> conOOSmoothed = new ConstructGen<double>(enabled.Count());
        ConstructGen<double> conOOOSmoothed = new ConstructGen<double>(enabled.Count());
        ConstructGen<double> conOOOOSmoothed = new ConstructGen<double>(enabled.Count());

        var listofAllRollDates = new List<DateTime>();
        var listOfAllOldDates = new List<DateTime>();

        for (int i = 0; i < con.ArrayLength; ++i)
        {
          var currentTuple = getItems(enabled[i], CTDValueGeneration.Current);
          var oldTuple = getItems(enabled[i], CTDValueGeneration.Old);
          var oldOldTuple = getItems(enabled[i], CTDValueGeneration.OldOld);
          var oooTuple = getItems(enabled[i], CTDValueGeneration.OOO);
          var ooooTuple = getItems(enabled[i], CTDValueGeneration.OOOO);

          con.SetColumnValues(i, currentTuple.Item2);
          conOld.SetColumnValues(i, oldTuple.Item2);
          conOldOld.SetColumnValues(i, oldOldTuple.Item2);
          conOOO.SetColumnValues(i, oooTuple.Item2);
          conOOOO.SetColumnValues(i, ooooTuple.Item2);

          {
            var smoothed = new double[con.Dates.Count];
            var oldSmoothed = new double[con.Dates.Count];
            var ooSmoothed = new double[con.Dates.Count];
            var oooSmoothed = new double[con.Dates.Count];
            var ooooSmoothed = new double[con.Dates.Count];
            smoothed[0] = currentTuple.Item2.Data[0];
            oldSmoothed[0] = oldTuple.Item2.Data[0];
            ooSmoothed[0] = oldOldTuple.Item2.Data[0];
            oooSmoothed[0] = oooTuple.Item2.Data[0];
            ooooSmoothed[0] = ooooTuple.Item2.Data[0];

            for (int j = 1; j < smoothed.Length; ++j)
            {
              // if the bond hasn't changed, then just adjust the previous value by change in the bond
              if (String.CompareOrdinal(currentTuple.Item1.Data[j].SymmetryCode, currentTuple.Item1.Data[j - 1].SymmetryCode) == 0)
              {
                smoothed[j] = smoothed[j - 1] + (currentTuple.Item2.Data[j] - currentTuple.Item2.Data[j - 1]);
                oldSmoothed[j] = oldSmoothed[j - 1] + (oldTuple.Item2.Data[j] - oldTuple.Item2.Data[j - 1]);
                ooSmoothed[j] = ooSmoothed[j - 1] + (oldOldTuple.Item2.Data[j] - oldOldTuple.Item2.Data[j - 1]);
                oooSmoothed[j] = oooSmoothed[j - 1] + (oooTuple.Item2.Data[j] - oooTuple.Item2.Data[j - 1]);                
              }
              // the bond has changed... yesterday's [current bond] has become the new [old bond], so adjust previous value by [old bond] value today - the [current bond] value yesterday
              else
              {
                smoothed[j] = smoothed[j - 1] + (oldTuple.Item2.Data[j] - currentTuple.Item2.Data[j - 1]);
                oldSmoothed[j] = oldSmoothed[j - 1] + (oldOldTuple.Item2.Data[j] - oldTuple.Item2.Data[j - 1]);
                ooSmoothed[j] = ooSmoothed[j - 1] + (oooTuple.Item2.Data[j] - oldOldTuple.Item2.Data[j - 1]);
                oooSmoothed[j] = oooSmoothed[j - 1] + (ooooTuple.Item2.Data[j] - oooTuple.Item2.Data[j - 1]);                
                listofAllRollDates.Add(currentTuple.Item1.Dates[j]);
                listOfAllOldDates.Add(currentTuple.Item1.Dates[j - 1]);
              }
            }
            conSmoothed.SetColumnValues(i, new DatedDataCollectionGen<double>(currentTuple.Item2.Dates, smoothed));
            conOldSmoothed.SetColumnValues(i, new DatedDataCollectionGen<double>(currentTuple.Item2.Dates, oldSmoothed));
            conOOSmoothed.SetColumnValues(i, new DatedDataCollectionGen<double>(currentTuple.Item2.Dates, ooSmoothed));
            conOOOSmoothed.SetColumnValues(i, new DatedDataCollectionGen<double>(currentTuple.Item2.Dates, oooSmoothed));
          }


        }

        primary = con.SumRows();
        old = conOld.SumRows();
        oldold = conOldOld.SumRows();
        ooo = conOOO.SumRows();
        oooo = conOOOO.SumRows();
        smthd = conSmoothed.SumRows();
        oldsmthd = conOldSmoothed.SumRows();
        oosmthd = conOOSmoothed.SumRows();
        ooosmthd = conOOOSmoothed.SumRows();
        

        oldDates = listOfAllOldDates.Distinct().OrderBy(x => x).ToArray();
        rollDates = listofAllRollDates.Distinct().OrderBy(x => x).ToArray();

      }

      return new ChartData()
      {
        OriginalData=primary,
        OldData=old,
        OldOldData = oldold,
        OOOData = ooo,
        OOOOData = oooo,
        SmoothedData=smthd,
        OldSmoothedData=oldsmthd,
        OOSmoothedData = oosmthd,
        OOOSmoothedData = ooosmthd,
        NewDates=rollDates,
        OldDates=oldDates
      };
    }
Esempio n. 4
0
    public void ShowPortfolioPnlProgression()
    {
      var pnl = new ConstructGen<double>(Positions.Select(x=>x.Security).ToArray());

      var flp = new System.Windows.Forms.FlowLayoutPanel();

      var listOfInfraBoxes = new List<Infragistics.Win.Misc.UltraGroupBox>();

      for (int i = 0; i < pnl.ArrayLength; ++i)
      {
        var posPnl = Positions[i].GeneratePnlSinceFix();

        for (int d = 0; d < posPnl.Length; ++d)
        {
          pnl.SetValue(posPnl.Dates[d], i, posPnl.Data[d].Close);
        }

        {
          Infragistics.Win.Misc.UltraGroupBox box = new Infragistics.Win.Misc.UltraGroupBox();
          box.Text = string.Format("{0} {1}", Positions[i].Security, Positions[i].Pnl.ToString("###0.0#;(###0.0#);-"));
          box.Tag = Positions[i].Pnl;
          box.Size = new System.Drawing.Size(250, 250);

          var chart = new SI.Controls.BarDataPointChart();
          chart.SetYAxisFormat("##0.0#");
          chart.Dock = System.Windows.Forms.DockStyle.Fill;
          chart.Create(posPnl);
          box.Controls.Add(chart);
          listOfInfraBoxes.Add(box);
        }
      }

      Infragistics.Win.Misc.UltraGroupBox[] boxArr = listOfInfraBoxes.OrderByDescending(x => (double)x.Tag).ToArray();

      {
        double max = 0d;
        foreach (Infragistics.Win.Misc.UltraGroupBox box in boxArr)
        {
          max = Math.Max(max, ((SI.Controls.BarDataPointChart)box.Controls[0]).YAxisAbsoluteMax);
        }

        foreach (Infragistics.Win.Misc.UltraGroupBox box in boxArr)
        {
          ((SI.Controls.BarDataPointChart)box.Controls[0]).SetMaxMinYAxisRange(max);
        }
      }

      foreach (Infragistics.Win.Misc.UltraGroupBox box in boxArr)
      {
        flp.Controls.Add(box);
      }


      pnl.SortKeys();

      for (int i = 0; i < pnl.ArrayLength; ++i)
      {
        DatedDataCollectionGen<double> col = pnl.GetColumnValuesAsDDC(i);
        double last = col.Data[0];

        for (int j = 1; j < col.Length; ++j)
        {
          double val = col.Data[j];

          if (val == 0d)
          {
            if (last != 0d)
            {
              pnl.SetValue(col.Dates[j], i, last);
            }
          }
          else
            last = val;
        }
      }

      DatedDataCollectionGen<double> total = pnl.SumRows();

      KeyValuePair<string, System.Windows.Forms.Control>[] cons = new KeyValuePair<string, System.Windows.Forms.Control>[3];

      var stack = new Controls.SimpleStackedColumnChart();

      stack.Create<string, string>(
        pnl.Dates.Select(x => x.ToString("HH:mm")).ToArray(),
        Positions.Select(x => x.Security).ToArray(),
        pnl.ToArray());
      cons[0] = new KeyValuePair<string, System.Windows.Forms.Control>("position attributed", stack);


      //stack.DisplayInShowForm(string.Format("{0} pnl progression, position attributed", this.Name));

      var lcdd = new SI.Controls.LineChartDataDisplay();
      lcdd.AddSeries(total.Dates, total.Data, Name, 40, "#0.0#");
      lcdd.SetXAxisFormat("HH:mm");
      //lcdd.DisplayInShowForm(string.Format("{0} total pnl progression", m_p.DisplayName));
      cons[1] = new KeyValuePair<string, Control>("total", lcdd);

      cons[2] = new KeyValuePair<string, Control>("comp", flp);

      cons.DisplayInShowForm(string.Format("{0} pnl progression", Name));

    }
Esempio n. 5
0
      public ChartData GetDataFromCarbonFrame()
      {
          var enabled = Components.Where(x => x.IsReady()).ToList();

          if (!enabled.Any())
              return null;
          
          var listofAllRollDates = new Dictionary<CTCTDType, Tuple<string, DateTime>[]>();
          var listOfAllOldDates = new Dictionary<CTCTDType, Tuple<string, DateTime>[]>();

          ConstructGen<double> con = new ConstructGen<double>(enabled.Count());
          ConstructGen<double> conOld = new ConstructGen<double>(enabled.Count());
          ConstructGen<double> conOldOld = new ConstructGen<double>(enabled.Count());
          ConstructGen<double> conSmoothed = new ConstructGen<double>(enabled.Count());          

          for (int i = 0; i < con.ArrayLength; ++i)
          {
              var curDataTuple = ChartComponentCarbonMediator.GetItemsFromCarbonFrame(enabled[i], g => g.CurrentResult, r => r.TrueSpread);
              con.SetColumnValues(i, curDataTuple.Item2);
              var oDataTuple = ChartComponentCarbonMediator.GetItemsFromCarbonFrame(enabled[i], g => g.OResult, r => r.TrueSpread);
              conOld.SetColumnValues(i, oDataTuple.Item2);
              var ooDataTuple = ChartComponentCarbonMediator.GetItemsFromCarbonFrame(enabled[i], g => g.OOResult, r => r.TrueSpread);
              conOldOld.SetColumnValues(i, ooDataTuple.Item2);
              var smoothDataTuple = ChartComponentCarbonMediator.GetItemsFromCarbonFrame(enabled[i], g => g.SmoothResult, r => r.TrueSpread);
              conSmoothed.SetColumnValues(i, smoothDataTuple.Item2);


              for (int j = 1; j < con.Dates.Count; ++j)
              {
                  // if the bond hasn't changed, then just adjust the previous value by change in the bond
                  if (j < curDataTuple.Item1.Data.Length)
                  { 
                      if (String.CompareOrdinal(curDataTuple.Item1.Data[j], curDataTuple.Item1.Data[j - 1]) != 0)
                      {
                          listofAllRollDates.AddOrAppendDictionaryValueArray(enabled[i].CTCTDType, new Tuple<string, DateTime>(enabled[i].Component + "\n" + curDataTuple.Item1.Data[j], curDataTuple.Item1.Dates[j]));
                          listOfAllOldDates.AddOrAppendDictionaryValueArray(enabled[i].CTCTDType, new Tuple<string, DateTime>(enabled[i].Component + "\n" + curDataTuple.Item1.Data[j - 1], curDataTuple.Item1.Dates[j - 1]));
                      }
                  }
              }
          }


          return new ChartData
          {
              OriginalData = con.SumRows(),
              OldData = conOld.SumRows(),
              OldOldData = conOldOld.SumRows(),
              SmoothedData = conSmoothed.SumRows(),

              NewDates = listofAllRollDates.SelectMany(d => d.Value.Select(v => v.Item2)).Distinct().OrderBy(x => x).ToArray(),
              OldDates = listOfAllOldDates.SelectMany(d => d.Value.Select(v => v.Item2)).Distinct().OrderBy(x => x).ToArray(),
              OldRollTypeDates = listOfAllOldDates.Select(k => new {k.Key, v = k.Value.Distinct().OrderBy(x => x).ToArray() } ).ToDictionary(k => k.Key, k => k.v),
              NewRollTypeDates = listofAllRollDates.Select(k => new { k.Key, v = k.Value.Distinct().OrderBy(x => x).ToArray() }).ToDictionary(k => k.Key, k => k.v),
          };

      }