Update score

This commit is contained in:
2025-03-01 23:20:01 +07:00
parent bcf9d21b0a
commit 6f4db52bbb

View File

@@ -5,28 +5,25 @@ public class BacktestScorer
// Updated weights without ProfitEfficiency
private static readonly Dictionary<string, double> Weights = new Dictionary<string, double>
{
{ "SharpeRatio", 0.22 }, // Increased weight
{ "GrowthPercentage", 0.22 }, // Increased weight
{ "GrowthPercentage", 0.30 }, // Increased weight for profitability
{ "SharpeRatio", 0.18 },
{ "MaxDrawdownPc", 0.15 },
{ "WinRate", 0.15 }, // Increased weight
{ "HodlComparison", 0.15 }, // Increased weight
{ "TradeCount", 0.06 },
{ "RecoveryTime", 0.04 },
{ "RiskAdjustedGrowth", 0.01 }
{ "HodlComparison", 0.15 },
{ "WinRate", 0.10 },
{ "ProfitabilityBonus", 0.07 }, // New direct profitability component
{ "TradeCount", 0.03 },
{ "RecoveryTime", 0.02 }
};
public static double CalculateTotalScore(BacktestScoringParams p)
{
try
{
// Detect inactive strategies
if (IsInactiveStrategy(p))
{
return Math.Min(CalculateBaseScore(p) * 0.3, 40);
}
var baseScore = CalculateBaseScore(p);
var finalScore = ApplyProfitabilityRules(baseScore, p);
var score = CalculateBaseScore(p);
return double.Clamp(score, 0, 100);
return double.Clamp(finalScore, 0, 100);
}
catch
{
@@ -38,19 +35,85 @@ public class BacktestScorer
{
var componentScores = new Dictionary<string, double>
{
{ "SharpeRatio", CalculateSharpeScore(p.SharpeRatio) },
{ "GrowthPercentage", CalculateGrowthScore(p.GrowthPercentage) },
{ "SharpeRatio", CalculateSharpeScore(p.SharpeRatio) },
{ "MaxDrawdownPc", CalculateDrawdownScore(p.MaxDrawdownPc) },
{ "WinRate", CalculateWinRateScore(p.WinRate, p.TradeCount) },
{ "HodlComparison", CalculateHodlComparisonScore(p.GrowthPercentage, p.HodlPercentage) },
{ "WinRate", CalculateWinRateScore(p.WinRate, p.TradeCount) },
{ "ProfitabilityBonus", CalculateProfitabilityBonus(p.GrowthPercentage) },
{ "TradeCount", CalculateTradeCountScore(p.TradeCount) },
{ "RecoveryTime", CalculateRecoveryScore(p.MaxDrawdownRecoveryTime) },
{ "RiskAdjustedGrowth", CalculateRiskAdjustedGrowthScore(p.GrowthPercentage, p.MaxDrawdownPc) }
{ "RecoveryTime", CalculateRecoveryScore(p.MaxDrawdownRecoveryTime) }
};
return componentScores.Sum(kvp => kvp.Value * Weights[kvp.Key]);
}
private static double ApplyProfitabilityRules(double baseScore, BacktestScoringParams p)
{
// 1. Negative PnL Penalty (Core Rule)
if (p.GrowthPercentage < 0)
{
baseScore = Math.Min(baseScore, 70) * GetNegativePnLMultiplier(p.GrowthPercentage);
}
// 2. Absolute PnL Validation (Additional Recommendation)
if (p.TotalPnL <= 0)
{
baseScore = Math.Min(baseScore, 50);
}
// 3. Win Rate Validation (Additional Recommendation)
if (p.WinRate < 0.3 && p.TradeCount > 10)
{
baseScore = Math.Min(baseScore, 60);
}
// 4. Minimum Profit Threshold (Additional Recommendation)
if (p.GrowthPercentage < 2 && p.TradeCount > 5)
{
baseScore = Math.Min(baseScore, 80);
}
return baseScore;
}
private static double CalculateGrowthScore(double growthPercentage)
{
// More aggressive penalty for negative growth
if (growthPercentage < 0)
{
return Math.Max(0, 40 + (growthPercentage * 2)); // -10% → 20, -20% → 0
}
// Require minimum 5% growth for full score
return growthPercentage switch
{
< 5 => growthPercentage * 15, // 2% → 30, 4% → 60
_ => 100
};
}
// Existing multiplier calculation
private static double GetNegativePnLMultiplier(double growthPercentage)
{
return growthPercentage switch
{
> -5 => 0.8,
> -10 => 0.6,
> -20 => 0.4,
_ => 0.2
};
}
private static double CalculateProfitabilityBonus(double growthPercentage)
{
return growthPercentage switch
{
> 0 => 100 * (1 - 1 / (1 + growthPercentage / 50)), // Diminishing returns
_ => 0
};
}
private static bool IsInactiveStrategy(BacktestScoringParams p)
{
// Detect strategies with no economic value
@@ -69,14 +132,6 @@ public class BacktestScorer
};
}
private static double CalculateGrowthScore(double growthPercentage)
{
if (growthPercentage < 0)
return Math.Max(0, 50 + (growthPercentage * 2)); // -5% → 40, -25% → 0
return Math.Min(100, (Math.Log(1 + growthPercentage) / Math.Log(1 + 1000)) * 100);
}
private static double CalculateDrawdownScore(double maxDrawdownPc)
{
return maxDrawdownPc switch