public async Task<double[]> CalcContToRisk(SysTimeSeries exposures_, DateTime asOf_, CarbonClient cc_)
    {
      // extract exposure on date
      var expOnDate = exposures_.Data.GetValues(asOf_);

      // get indexes for instruments in covariance
      var indexes = new Tuple<int, bool>[expOnDate.Length];
      for (int i = 0; i < indexes.Length; ++i)
        indexes[i] = await FindIndexOfInstrument(exposures_.Data.ColumnHeadings[i], cc_);

      // translate up the exposures into same dimensions as covariance
      var exposuresInCovarianceDimensions = new double[Keys.Count];
      for (int i = 0; i < indexes.Length; ++i)
      {
        if (indexes[i] == null) continue;
        exposuresInCovarianceDimensions[indexes[i].Item1] = (indexes[i].Item2 ? -1d : 1d) * expOnDate[i];
      }

      // calculate contributions to risk
      var contToRisk = GetContToVar(exposuresInCovarianceDimensions);

      // translate back into porfolio dimensions
      var riskInPortfolioDimensions = new double[expOnDate.Length];
      for (int i = 0; i < riskInPortfolioDimensions.Length; ++i)
      {
        if (indexes[i] == null) continue;
        riskInPortfolioDimensions[i] = contToRisk[indexes[i].Item1];
      }

      return riskInPortfolioDimensions;
    }
    public async Task<double> CalcVol(SysTimeSeries exposures_, DateTime asOf_, CarbonClient cc_)
    {
      // extract exposure on date
      var expOnDate = exposures_.Data.GetValues(asOf_);

      // get indexes for instruments in covariance
      var indexes = new Tuple<int,bool>[expOnDate.Length];
      for (int i = 0; i < indexes.Length; ++i)
        indexes[i] = await FindIndexOfInstrument(exposures_.Data.ColumnHeadings[i], cc_);

      // translate up the exposures into same dimensions as covariance
      var exposuresInCovarianceDimensions = new double[Keys.Count];
      for (int i = 0; i < indexes.Length; ++i)
      {
        if (indexes[i] == null) continue;
        exposuresInCovarianceDimensions[indexes[i].Item1] = (indexes[i].Item2 ? -1d : 1d) * expOnDate[i];
      }

      return GetVol(exposuresInCovarianceDimensions);
    }
    public async Task<double> CalcLatestVol(SysTimeSeries exposures_, CarbonClient cc_)
    {
      if (exposures_ == null || exposures_.Data == null || exposures_.Data.Keys.Count == 0) return double.NaN;

      return await CalcVol(exposures_, exposures_.Data.Keys[exposures_.Data.Keys.Count - 1], cc_);
    }
    public async Task<double[]> CalcLatestContToRisk(SysTimeSeries exposures_, CarbonClient cc_)
    {
      if (exposures_ == null || exposures_.Data == null || exposures_.Data.Keys.Count == 0) return null;

      return await CalcContToRisk(exposures_, exposures_.Data.Keys[exposures_.Data.Keys.Count - 1], cc_);
    }