2
\$\begingroup\$

I have implemented mathematical functions using a C# library. I basically need to output data by the RiskMatrixByFunds in the following format.

Key will contain Id and value will contain collection of string, double, double

For example:

Id 1

value

{'ArithmeticMean', 12.34, 3.44},
{'AverageGain', 12.35, 3.45},
{'AverageLoss', 12.36, 3.46},

I have used a Dictionary structure that will contain the int and list of tuple collection.

Let me know if it can be enhanced, any ideas on magic strings used, a better way to implement it.

public class RiskMatrix : IRiskMatrix
{

    public (double Monthly, double Annual) ArithmeticMean(IEnumerable<double> ReturnsList)
    {
        double returnList = ReturnsList.Mean();
        return (Monthly: returnList, Annual: returnList * Math.Pow(12, 0.5));
    }

    public (double Monthly, double Annual) AverageGain(IEnumerable<double> ReturnsList)
    {

        double returnList = ReturnsList.GainMean();
        return (Monthly: returnList, Annual: returnList * Math.Pow(12, 0.5));
    }

    public (double Monthly, double Annual) AverageLoss(IEnumerable<double> ReturnsList)
    {
        double returnList = ReturnsList.LossMean();
        return (Monthly: returnList, Annual: returnList * Math.Pow(12, 0.5));
    }


    public Dictionary<int, List<Tuple<string,double, double>>> RiskMatrixByFunds(Dictionary<int, IEnumerable<double>> ReturnsList)
    {
        Dictionary<int, List<Tuple<string ,double, double>>> returnsList = new Dictionary<int, List<Tuple<string,double, double>>>();
        List <Tuple<string, double, double>> list = null;

        foreach (KeyValuePair<int, IEnumerable<double>> entry in ReturnsList)
        {
            list = new List<Tuple<string, double, double>>();
            (double Monthly, double Annual) arithmeticMeanResult = ArithmeticMean(entry.Value);
            list.Add(new Tuple<string, double, double>("ArithmeticMean", arithmeticMeanResult.Monthly, arithmeticMeanResult.Annual));
            (double Monthly, double Annual) averageGainResult = AverageGain(entry.Value);
            list.Add(new Tuple<string, double, double>("AverageGain", averageGainResult.Monthly, averageGainResult.Annual));
            (double Monthly, double Annual) averageLossResult = AverageLoss(entry.Value);
            list.Add(new Tuple<string, double, double>("AverageLoss", averageLossResult.Monthly, averageLossResult.Annual));
            (double Monthly, double Annual) betaCorrelationresult = BetaCorrelation(entry.Value);

           returnsList.Add(entry.Key, list);
        }
        return returnsList;
    }   
}   
\$\endgroup\$
4
\$\begingroup\$

There might be a reason why you used a List<Tuple<string ,double, double>>. E.g. if you need to pass the data to an existing library or your UI needs to bind to a list. Otherwise I would recommend to create a dedicated class

public class RiskStatistics
{
    public double ArithmeticMeanMonthly { get; set; }
    public double ArithmeticMeanAnnual { get; set; }

    public double AverageGainMonthly { get; set; }
    public double AverageGainAnnual { get; set; }

    public double AverageLossMonthly { get; set; }
    public double AverageLossAnnual { get; set; }
}

Since the properties are named, there's no need for magic strings. This makes the creation and usage of the risk matrix less convoluted:

public Dictionary<int, RiskStatistics> RiskMatrixByFunds(
    Dictionary<int, IEnumerable<double>> returnsLists)
{
    var riskMatrixDict = new Dictionary<int, RiskStatistics>();

    foreach (KeyValuePair<int, IEnumerable<double>> entry in returnsLists) {
        var risk = new RiskStatistics();
        (risk.ArithmeticMeanMonthly, risk.ArithmeticMeanAnnual) = ArithmeticMean(entry.Value);
        (risk.AverageGainMonthly, risk.AverageGainAnnual) = AverageGain(entry.Value);
        (risk.AverageLossMonthly, risk.AverageLossAnnual) = AverageLoss(entry.Value);
        riskMatrixDict.Add(entry.Key, risk);
    }
    return riskMatrixDict;
}

You could also calculate the annual values on the fly. This would make the creation even easier. Here the adapted average gain properties as an example:

private static readonly double Sqrt12 = Math.Pow(12, 0.5);

public double ArithmeticMeanMonthly { get; set; }
public double ArithmeticMeanAnnual => ArithmeticMeanMonthly * Sqrt12;

With this adapted RiskStatistics class, you could directly assign from the extension methods and skip the methods returning tuples.

var risk = new RiskStatistics {
    ArithmeticMeanMonthly = entry.Value.Mean(),
    AverageGainMonthly = entry.Value.GainMean(),
    AverageLossMonthly = entry.Value.LossMean()
};
riskMatrixDict.Add(entry.Key, risk);

The annual values are read-only and need not to be assigned.

\$\endgroup\$
  • \$\begingroup\$ Good idea. Integrated it in my answer. Multiplication is fast and should have no noticeable impact on speed. \$\endgroup\$ – Olivier Jacot-Descombes Apr 8 at 12:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.