我正在计算List<BacktestResult>
中每个Pair
的利润及其交易计数,以及BacktestResult
对象本身,因为我需要它的属性,例如打印它们。这就是下面的foreach
所做的。然后我想要获得最大利润的目标。代码按预期工作,但我想完全在LINQ中重新创建它,例如没有丑陋的Max()检查。它应该返回var bestPair = BacktestResult object of the maximum result.Sum(e => e.ProfitPercentage)
。
(decimal Max, string Pair) value = (int.MinValue, null);
foreach (var result in data.GroupBy(e => e.Pair)
.Select(e => new { Pair = e.Key, Count = e.Count(), Value = e }))
{
var profitSum = result.Value.Sum(e => e.ProfitPercentage);
if (profitSum > value.Max)
{
value.Max = profitSum;
value.Pair = result.Pair;
}
}
public class BacktestResult
{
public string Pair { get; set; }
public decimal ProfitPercentage { get; set; }
public decimal ProfitAbs { get; set; }
public decimal OpenRate { get; set; }
public decimal CloseRate { get; set; }
public DateTime OpenDate { get; set; }
public DateTime CloseDate { get; set; }
public decimal OpenFee { get; set; }
public decimal CloseFee { get; set; }
public decimal Amount { get; set; }
public decimal TradeDuration { get; set; }
public SellType SellReason { get; set; }
}
public static class LinqExtensions
{
public static T MaxBy<T, R>(this IEnumerable<T> en, Func<T, R> evaluate) where R : IComparable<R>
{
return en.Select(t => new Tuple<T, R>(t, evaluate(t)))
.Aggregate((max, next) => next.Item2.CompareTo(max.Item2) > 0 ? next : max).Item1;
}
public static T MinBy<T, R>(this IEnumerable<T> en, Func<T, R> evaluate) where R : IComparable<R>
{
return en.Select(t => new Tuple<T, R>(t, evaluate(t)))
.Aggregate((max, next) => next.Item2.CompareTo(max.Item2) < 0 ? next : max).Item1;
}
}
你可以试试
string pairOfGroupWithHighestProfitSum = data.GroupBy(e => e.Pair).
Select(e => new { Pair = e.Key, Count = e.Count(), ProfitSum = e.Sum(e => e.ProfitPercentage), Value = e }).
OrderByDescending(e => e.ProfitSum).
FirstOrDefault()?.Pair;
如果你的data
是空的,它将为null,否则你将获得具有最高利润总额的组的对。
如果你使用。net Core,你不会因为先排序然后取第一个值来寻找最大值而受到性能损失。见https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/5.0/orderby-firstordefault-complexity-increase