/// <summary> /// Upside Potential Ratio,compared to Sortino, was a further improvement, extending the /// measurement of only upside on the numerator, and only downside of the /// denominator of the ratio equation. /// (分子只考虑超过MAR部分,分母只考虑DownsideDeviation的下跌风险) /// </summary> func UpsidePotentialRatio(Ra *utils.SlidingWindow, MAR float64) (float64, error) { //var r = Ra.Where<float64>(singleData => singleData > MAR).ToList<float64>(); r, err := utils.AboveValue(Ra, MAR) if err != nil { return math.NaN(), err } var length int method := "subset" switch method { case "full": length = Ra.Count() break case "subset": length = r.Count() break default: return math.NaN(), errors.New("In UpsidePotentialRatio, method is default !!!") } add_Sliding, err := utils.Add(-MAR, r) if err != nil { return math.NaN(), err } dd2Data, err := DownsideDeviation2(Ra, MAR) if err != nil { return math.NaN(), err } var result = (add_Sliding.Sum() / float64(length)) / dd2Data return result, nil }
/// <summary> /// subset of returns that are /// more than the target (or Minimum Acceptable Returns (MAR)) returns and /// divide the length of this subset by the total number of returns. /// (超过MAR的频率) /// </summary> func UpsideFrequency(Ra *utils.SlidingWindow, MAR float64) (float64, error) { aboveMAR, err := utils.AboveValue(Ra, MAR) if err != nil { return math.NaN(), err } return float64(aboveMAR.Count()) / float64(Ra.Count()), nil }
/// <summary> /// Upside Risk is the similar of semideviation taking the return above the /// Minimum Acceptable Return instead of using the mean return or zero. /// (一般来说,非对称类的比较,单求此统计量意义有限) /// </summary> func UpsideRisk(Ra *utils.SlidingWindow, MAR float64, stat string) (float64, error) { r, err := utils.AboveValue(Ra, MAR) if err != nil { return math.NaN(), err } var length float64 method := "subset" switch method { case "full": length = float64(Ra.Count()) break case "subset": length = float64(r.Count()) break default: return math.NaN(), errors.New("In Upside Risk, method is default !!!") } if length <= 0 { return 0, nil } var result float64 switch stat { case "risk": add_Sliding, err := utils.Add(-MAR, r) if err != nil { return math.NaN(), err } pow_Sliding, err := utils.Power(add_Sliding, 2.0) if err != nil { return math.NaN(), err } multi_Sliding, err := utils.Multi(1.0/length, pow_Sliding) if err != nil { return math.NaN(), err } result = math.Sqrt(multi_Sliding.Sum()) break case "variance": add_Sliding, err := utils.Add(-MAR, r) if err != nil { return math.NaN(), err } pow_Sliding, err := utils.Power(add_Sliding, 2.0) if err != nil { return math.NaN(), err } multi_Sliding, err := utils.Multi(1.0/length, pow_Sliding) if err != nil { return math.NaN(), err } result = multi_Sliding.Sum() break case "potential": add_Sliding, err := utils.Add(-MAR, r) if err != nil { return math.NaN(), err } multi_Slding, err := utils.Multi(1.0/length, add_Sliding) if err != nil { return math.NaN(), err } result = multi_Slding.Sum() break default: return math.NaN(), errors.New("In UpSide Risk, method is default !!!") } return result, nil }