Update score
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user