Update scoring
This commit is contained in:
@@ -676,7 +676,6 @@ namespace Managing.Application.Tests
|
|||||||
|
|
||||||
var scoringParams = new BacktestScoringParams(
|
var scoringParams = new BacktestScoringParams(
|
||||||
sharpeRatio: (double)(backtestResult.Statistics?.SharpeRatio ?? 0),
|
sharpeRatio: (double)(backtestResult.Statistics?.SharpeRatio ?? 0),
|
||||||
maxDrawdownPc: (double)(backtestResult.Statistics?.MaxDrawdownPc ?? 0),
|
|
||||||
growthPercentage: (double)backtestResult.GrowthPercentage,
|
growthPercentage: (double)backtestResult.GrowthPercentage,
|
||||||
hodlPercentage: (double)backtestResult.HodlPercentage,
|
hodlPercentage: (double)backtestResult.HodlPercentage,
|
||||||
winRate: backtestResult.WinRate / 100.0, // Convert percentage to decimal
|
winRate: backtestResult.WinRate / 100.0, // Convert percentage to decimal
|
||||||
@@ -686,6 +685,7 @@ namespace Managing.Application.Tests
|
|||||||
maxDrawdownRecoveryTime: backtestResult.Statistics?.MaxDrawdownRecoveryTime ?? TimeSpan.Zero,
|
maxDrawdownRecoveryTime: backtestResult.Statistics?.MaxDrawdownRecoveryTime ?? TimeSpan.Zero,
|
||||||
maxDrawdown: backtestResult.Statistics?.MaxDrawdown ?? 0,
|
maxDrawdown: backtestResult.Statistics?.MaxDrawdown ?? 0,
|
||||||
initialBalance: config.BotTradingBalance,
|
initialBalance: config.BotTradingBalance,
|
||||||
|
tradingBalance: config.BotTradingBalance,
|
||||||
startDate: backtestResult.StartDate,
|
startDate: backtestResult.StartDate,
|
||||||
endDate: backtestResult.EndDate,
|
endDate: backtestResult.EndDate,
|
||||||
timeframe: config.Timeframe
|
timeframe: config.Timeframe
|
||||||
|
|||||||
@@ -302,7 +302,6 @@ namespace Managing.Application.Backtesting
|
|||||||
var fees = bot.GetTotalFees();
|
var fees = bot.GetTotalFees();
|
||||||
var scoringParams = new BacktestScoringParams(
|
var scoringParams = new BacktestScoringParams(
|
||||||
sharpeRatio: (double)stats.SharpeRatio,
|
sharpeRatio: (double)stats.SharpeRatio,
|
||||||
maxDrawdownPc: (double)stats.MaxDrawdownPc,
|
|
||||||
growthPercentage: (double)growthPercentage,
|
growthPercentage: (double)growthPercentage,
|
||||||
hodlPercentage: (double)hodlPercentage,
|
hodlPercentage: (double)hodlPercentage,
|
||||||
winRate: winRate,
|
winRate: winRate,
|
||||||
@@ -311,7 +310,8 @@ namespace Managing.Application.Backtesting
|
|||||||
tradeCount: bot.Positions.Count,
|
tradeCount: bot.Positions.Count,
|
||||||
maxDrawdownRecoveryTime: stats.MaxDrawdownRecoveryTime,
|
maxDrawdownRecoveryTime: stats.MaxDrawdownRecoveryTime,
|
||||||
maxDrawdown: stats.MaxDrawdown,
|
maxDrawdown: stats.MaxDrawdown,
|
||||||
initialBalance: config.BotTradingBalance,
|
initialBalance: bot.WalletBalances.FirstOrDefault().Value,
|
||||||
|
tradingBalance: config.BotTradingBalance,
|
||||||
startDate: candles[0].Date,
|
startDate: candles[0].Date,
|
||||||
endDate: candles.Last().Date,
|
endDate: candles.Last().Date,
|
||||||
timeframe: config.Timeframe
|
timeframe: config.Timeframe
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ namespace Managing.Domain.Backtests;
|
|||||||
public class BacktestScoringParams
|
public class BacktestScoringParams
|
||||||
{
|
{
|
||||||
public double SharpeRatio { get; }
|
public double SharpeRatio { get; }
|
||||||
public double MaxDrawdownPc { get; }
|
|
||||||
public double GrowthPercentage { get; }
|
public double GrowthPercentage { get; }
|
||||||
public double HodlPercentage { get; }
|
public double HodlPercentage { get; }
|
||||||
public double WinRate { get; }
|
public double WinRate { get; }
|
||||||
@@ -17,14 +16,13 @@ public class BacktestScoringParams
|
|||||||
// New properties for enhanced scoring
|
// New properties for enhanced scoring
|
||||||
public decimal MaxDrawdown { get; }
|
public decimal MaxDrawdown { get; }
|
||||||
public decimal InitialBalance { get; }
|
public decimal InitialBalance { get; }
|
||||||
|
public decimal TradingBalance { get; }
|
||||||
public DateTime StartDate { get; }
|
public DateTime StartDate { get; }
|
||||||
public DateTime EndDate { get; }
|
public DateTime EndDate { get; }
|
||||||
public decimal FeesPaid { get; }
|
|
||||||
public Timeframe Timeframe { get; }
|
public Timeframe Timeframe { get; }
|
||||||
|
|
||||||
public BacktestScoringParams(
|
public BacktestScoringParams(
|
||||||
double sharpeRatio,
|
double sharpeRatio,
|
||||||
double maxDrawdownPc,
|
|
||||||
double growthPercentage,
|
double growthPercentage,
|
||||||
double hodlPercentage,
|
double hodlPercentage,
|
||||||
double winRate,
|
double winRate,
|
||||||
@@ -34,12 +32,12 @@ public class BacktestScoringParams
|
|||||||
TimeSpan maxDrawdownRecoveryTime,
|
TimeSpan maxDrawdownRecoveryTime,
|
||||||
decimal maxDrawdown = 0,
|
decimal maxDrawdown = 0,
|
||||||
decimal initialBalance = 0,
|
decimal initialBalance = 0,
|
||||||
|
decimal tradingBalance = 0,
|
||||||
DateTime startDate = default,
|
DateTime startDate = default,
|
||||||
DateTime endDate = default,
|
DateTime endDate = default,
|
||||||
Timeframe timeframe = Timeframe.OneHour)
|
Timeframe timeframe = Timeframe.OneHour)
|
||||||
{
|
{
|
||||||
SharpeRatio = sharpeRatio;
|
SharpeRatio = sharpeRatio;
|
||||||
MaxDrawdownPc = maxDrawdownPc;
|
|
||||||
GrowthPercentage = growthPercentage;
|
GrowthPercentage = growthPercentage;
|
||||||
HodlPercentage = hodlPercentage;
|
HodlPercentage = hodlPercentage;
|
||||||
WinRate = winRate;
|
WinRate = winRate;
|
||||||
@@ -49,6 +47,7 @@ public class BacktestScoringParams
|
|||||||
MaxDrawdownRecoveryTime = maxDrawdownRecoveryTime;
|
MaxDrawdownRecoveryTime = maxDrawdownRecoveryTime;
|
||||||
MaxDrawdown = maxDrawdown;
|
MaxDrawdown = maxDrawdown;
|
||||||
InitialBalance = initialBalance;
|
InitialBalance = initialBalance;
|
||||||
|
TradingBalance = tradingBalance;
|
||||||
StartDate = startDate;
|
StartDate = startDate;
|
||||||
EndDate = endDate;
|
EndDate = endDate;
|
||||||
Timeframe = timeframe;
|
Timeframe = timeframe;
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ public class BacktestScorer
|
|||||||
{
|
{
|
||||||
{ "GrowthPercentage", 0.20 },
|
{ "GrowthPercentage", 0.20 },
|
||||||
{ "SharpeRatio", 0.15 },
|
{ "SharpeRatio", 0.15 },
|
||||||
{ "MaxDrawdownUsd", 0.15 },
|
|
||||||
{ "HodlComparison", 0.10 }, // Increased from 0.05 to 0.15
|
{ "HodlComparison", 0.10 }, // Increased from 0.05 to 0.15
|
||||||
{ "WinRate", 0.12 },
|
{ "WinRate", 0.12 },
|
||||||
{ "ProfitabilityBonus", 0.08 },
|
{ "ProfitabilityBonus", 0.08 },
|
||||||
@@ -16,7 +15,7 @@ public class BacktestScorer
|
|||||||
{ "RecoveryTime", 0.02 },
|
{ "RecoveryTime", 0.02 },
|
||||||
{ "TestDuration", 0.03 },
|
{ "TestDuration", 0.03 },
|
||||||
{ "FeesImpact", 0.02 },
|
{ "FeesImpact", 0.02 },
|
||||||
{ "RiskAdjustedReturn", 0.08 } // New component
|
{ "RiskAdjustedReturn", 0.23 } // Increased from 0.08 to 0.23 (absorbed MaxDrawdownUsd weight)
|
||||||
};
|
};
|
||||||
|
|
||||||
public static double CalculateTotalScore(BacktestScoringParams p)
|
public static double CalculateTotalScore(BacktestScoringParams p)
|
||||||
@@ -73,15 +72,14 @@ public class BacktestScorer
|
|||||||
{
|
{
|
||||||
{ "GrowthPercentage", CalculateGrowthScore(p.GrowthPercentage, result) },
|
{ "GrowthPercentage", CalculateGrowthScore(p.GrowthPercentage, result) },
|
||||||
{ "SharpeRatio", CalculateSharpeScore(p.SharpeRatio, result) },
|
{ "SharpeRatio", CalculateSharpeScore(p.SharpeRatio, result) },
|
||||||
{ "MaxDrawdownUsd", CalculateDrawdownUsdScore(p.MaxDrawdown, p.InitialBalance, result) },
|
|
||||||
{ "HodlComparison", CalculateHodlComparisonScore(p.GrowthPercentage, p.HodlPercentage, result) },
|
{ "HodlComparison", CalculateHodlComparisonScore(p.GrowthPercentage, p.HodlPercentage, result) },
|
||||||
{ "WinRate", CalculateWinRateScore(p.WinRate, p.TradeCount, result) },
|
{ "WinRate", CalculateWinRateScore(p.WinRate, p.TradeCount, result) },
|
||||||
{ "ProfitabilityBonus", CalculateProfitabilityBonus(p.GrowthPercentage, result) },
|
{ "ProfitabilityBonus", CalculateProfitabilityBonus(p.GrowthPercentage, result) },
|
||||||
{ "TradeCount", CalculateTradeCountScore(p.TradeCount, result) },
|
{ "TradeCount", CalculateTradeCountScore(p.TradeCount, result) },
|
||||||
{ "RecoveryTime", CalculateRecoveryScore(p.MaxDrawdownRecoveryTime, p.Timeframe, result) },
|
{ "RecoveryTime", CalculateRecoveryScore(p.MaxDrawdownRecoveryTime, p.Timeframe, result) },
|
||||||
{ "TestDuration", CalculateTestDurationScore(p.StartDate, p.EndDate, p.Timeframe, result) },
|
{ "TestDuration", CalculateTestDurationScore(p.StartDate, p.EndDate, p.Timeframe, result) },
|
||||||
{ "FeesImpact", CalculateFeesImpactScore(p.FeesPaid, p.InitialBalance, (decimal)p.TotalPnL, result) },
|
{ "FeesImpact", CalculateFeesImpactScore(p.Fees, p.TotalPnL, result) },
|
||||||
{ "RiskAdjustedReturn", CalculateRiskAdjustedReturnScore(p.TotalPnL, p.MaxDrawdown, p.InitialBalance, result) }
|
{ "RiskAdjustedReturn", CalculateRiskAdjustedReturnScore(p.TotalPnL, p.MaxDrawdown, p.TradingBalance, result) }
|
||||||
};
|
};
|
||||||
|
|
||||||
var totalScore = componentScores.Sum(kvp => kvp.Value * Weights[kvp.Key]);
|
var totalScore = componentScores.Sum(kvp => kvp.Value * Weights[kvp.Key]);
|
||||||
@@ -102,15 +100,14 @@ public class BacktestScorer
|
|||||||
{
|
{
|
||||||
"GrowthPercentage" => $"Growth of {p.GrowthPercentage:F2}% (target: 10% for full score)",
|
"GrowthPercentage" => $"Growth of {p.GrowthPercentage:F2}% (target: 10% for full score)",
|
||||||
"SharpeRatio" => $"Sharpe ratio of {p.SharpeRatio:F2} (target: 4.0 for full score)",
|
"SharpeRatio" => $"Sharpe ratio of {p.SharpeRatio:F2} (target: 4.0 for full score)",
|
||||||
"MaxDrawdownUsd" => $"Max drawdown of ${p.MaxDrawdown:F2} ({p.MaxDrawdownPc:F1}% of balance)",
|
|
||||||
"HodlComparison" => $"Strategy vs HODL: {p.GrowthPercentage:F2}% vs {p.HodlPercentage:F2}% (difference: {p.GrowthPercentage - p.HodlPercentage:F2}%)",
|
"HodlComparison" => $"Strategy vs HODL: {p.GrowthPercentage:F2}% vs {p.HodlPercentage:F2}% (difference: {p.GrowthPercentage - p.HodlPercentage:F2}%)",
|
||||||
"WinRate" => $"Win rate of {p.WinRate * 100:F1}% with {p.TradeCount} trades",
|
"WinRate" => $"Win rate of {p.WinRate:F2} with {p.TradeCount} trades", // Show as decimal
|
||||||
"ProfitabilityBonus" => $"Bonus for positive growth of {p.GrowthPercentage:F2}%",
|
"ProfitabilityBonus" => $"Bonus for positive growth of {p.GrowthPercentage:F2}%",
|
||||||
"TradeCount" => $"{p.TradeCount} trades executed (minimum 5, optimal 50+)",
|
"TradeCount" => $"{p.TradeCount} trades executed (minimum 5, optimal 50+)",
|
||||||
"RecoveryTime" => $"Recovery time: {p.MaxDrawdownRecoveryTime.TotalDays:F1} days",
|
"RecoveryTime" => $"Recovery time: {p.MaxDrawdownRecoveryTime.TotalDays:F1} days",
|
||||||
"TestDuration" => $"Test duration: {(p.EndDate - p.StartDate).TotalDays:F1} days",
|
"TestDuration" => $"Test duration: {(p.EndDate - p.StartDate).TotalDays:F1} days",
|
||||||
"FeesImpact" => $"Fees: ${p.FeesPaid:F2} ({p.FeesPaid / p.InitialBalance * 100:F2}% of balance)",
|
"FeesImpact" => $"Fees: ${p.Fees:F2} ({(p.TotalPnL > 0 ? p.Fees / p.TotalPnL * 100 : 0):F2}% of PnL)",
|
||||||
"RiskAdjustedReturn" => $"PnL/Drawdown ratio: {p.TotalPnL / (double)p.MaxDrawdown:F2}:1",
|
"RiskAdjustedReturn" => $"PnL/TradingBalance Drawdown ratio: {p.TotalPnL / (double)p.MaxDrawdown:F2}:1 (MaxDD: ${p.MaxDrawdown:F2} vs PnL: ${p.TotalPnL:F2})",
|
||||||
_ => $"Component score: {score:F1}"
|
_ => $"Component score: {score:F1}"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -147,12 +144,16 @@ public class BacktestScorer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 5. Drawdown Penalty (Dynamic) - Enhanced to consider PnL ratio
|
// 5. Drawdown Penalty (Dynamic) - Enhanced to consider PnL ratio
|
||||||
if (p.MaxDrawdownPc > 20)
|
if (p.TradingBalance > 0 && p.MaxDrawdown > 0)
|
||||||
{
|
{
|
||||||
var drawdownPenalty = (p.MaxDrawdownPc - 20) * 0.02; // 2% penalty per 1% above 20%
|
var drawdownPercentage = (double)(p.MaxDrawdown / p.TradingBalance * 100);
|
||||||
var newMultiplier = Math.Max(0.3, 1 - drawdownPenalty);
|
if (drawdownPercentage > 20)
|
||||||
penaltyMultiplier *= newMultiplier;
|
{
|
||||||
result.AddPenaltyCheck("High Drawdown", newMultiplier, $"Drawdown of {p.MaxDrawdownPc:F1}% above 20% threshold applied {drawdownPenalty:F1}% penalty");
|
var drawdownPenalty = (drawdownPercentage - 20) * 0.02; // 2% penalty per 1% above 20%
|
||||||
|
var newMultiplier = Math.Max(0.3, 1 - drawdownPenalty);
|
||||||
|
penaltyMultiplier *= newMultiplier;
|
||||||
|
result.AddPenaltyCheck("High Drawdown", newMultiplier, $"Drawdown of {drawdownPercentage:F1}% above 20% threshold applied {drawdownPenalty:F1}% penalty");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. Enhanced Drawdown vs PnL Penalty
|
// 6. Enhanced Drawdown vs PnL Penalty
|
||||||
@@ -193,17 +194,17 @@ public class BacktestScorer
|
|||||||
|
|
||||||
private static double CalculateGrowthScore(double growthPercentage, BacktestScoringResult result)
|
private static double CalculateGrowthScore(double growthPercentage, BacktestScoringResult result)
|
||||||
{
|
{
|
||||||
// More aggressive scoring - harder to reach 100
|
// Negative growth always scores 0
|
||||||
if (growthPercentage < 0)
|
if (growthPercentage < 0)
|
||||||
{
|
{
|
||||||
return Math.Max(0, 20 + (growthPercentage * 1.5)); // -10% → 5, -20% → 0
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Require minimum 10% growth for full score (increased from 5%)
|
|
||||||
return growthPercentage switch
|
return growthPercentage switch
|
||||||
{
|
{
|
||||||
< 5 => growthPercentage * 8, // 2% → 16, 4% → 32
|
< 5 => growthPercentage * 4, // 2% → 8, 4% → 16
|
||||||
< 10 => 40 + (growthPercentage - 5) * 12, // 5% → 40, 7% → 64, 9% → 88
|
< 10 => 20 + (growthPercentage - 5) * 6, // 5% → 20, 7% → 32, 9% → 44
|
||||||
|
< 20 => 50 + (growthPercentage - 10) * 5, // 10% → 50, 15% → 75, 19% → 95
|
||||||
_ => 100
|
_ => 100
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -230,30 +231,23 @@ public class BacktestScorer
|
|||||||
|
|
||||||
private static double CalculateSharpeScore(double sharpeRatio, BacktestScoringResult result)
|
private static double CalculateSharpeScore(double sharpeRatio, BacktestScoringResult result)
|
||||||
{
|
{
|
||||||
return sharpeRatio switch
|
// Multiply Sharpe ratio by 100 for more accurate scoring
|
||||||
|
var adjustedSharpeRatio = sharpeRatio * 100;
|
||||||
|
|
||||||
|
return adjustedSharpeRatio switch
|
||||||
{
|
{
|
||||||
< 0 => 0,
|
< 0 => 0,
|
||||||
> 4 => 100, // Increased threshold from 3 to 4
|
> 4 => 100, // Increased threshold from 3 to 4
|
||||||
_ => (sharpeRatio / 4) * 100
|
_ => (adjustedSharpeRatio / 4) * 100
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double CalculateDrawdownUsdScore(decimal maxDrawdown, decimal initialBalance, BacktestScoringResult result)
|
|
||||||
{
|
|
||||||
if (initialBalance <= 0) return 0;
|
|
||||||
|
|
||||||
var drawdownPercentage = (double)(maxDrawdown / initialBalance * 100);
|
|
||||||
return drawdownPercentage switch
|
|
||||||
{
|
|
||||||
> 30 => 0, // 30% drawdown in USD = 0 score
|
|
||||||
_ => 100 - Math.Pow(drawdownPercentage / 30 * 100, 1.5) / 100
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static double CalculateWinRateScore(double winRate, int tradeCount, BacktestScoringResult result)
|
private static double CalculateWinRateScore(double winRate, int tradeCount, BacktestScoringResult result)
|
||||||
{
|
{
|
||||||
// Base win rate score
|
// Use winRate as a decimal (e.g., 0.55 for 55%)
|
||||||
var baseScore = winRate * 100;
|
var baseScore = winRate;
|
||||||
|
|
||||||
// Significance factor - more aggressive
|
// Significance factor - more aggressive
|
||||||
var significanceFactor = Math.Min(1, (tradeCount - 5) / 50.0); // Start at 5 trades, full significance at 55 trades
|
var significanceFactor = Math.Min(1, (tradeCount - 5) / 50.0); // Start at 5 trades, full significance at 55 trades
|
||||||
@@ -338,45 +332,51 @@ public class BacktestScorer
|
|||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double CalculateFeesImpactScore(decimal feesPaid, decimal initialBalance, decimal totalPnL, BacktestScoringResult result)
|
private static double CalculateFeesImpactScore(double fees, double totalPnL, BacktestScoringResult result)
|
||||||
{
|
{
|
||||||
if (initialBalance <= 0) return 0;
|
if (totalPnL <= 0) return 0;
|
||||||
|
|
||||||
var feesPercentage = (double)(feesPaid / initialBalance * 100);
|
var feesPercentage = fees / totalPnL * 100;
|
||||||
var pnlPercentage = (double)(totalPnL / initialBalance * 100);
|
|
||||||
|
|
||||||
// If fees are higher than PnL, heavy penalty
|
// If fees are higher than PnL, heavy penalty
|
||||||
if (feesPaid > totalPnL && totalPnL > 0)
|
if (fees > totalPnL)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fee efficiency score
|
// Fee efficiency score based on PnL
|
||||||
var feeEfficiency = feesPercentage switch
|
var feeEfficiency = feesPercentage switch
|
||||||
{
|
{
|
||||||
> 5 => 0, // More than 5% fees = 0
|
> 20 => 0, // More than 20% fees = 0
|
||||||
> 2 => 50 - (feesPercentage - 2) * 16.67, // 2-5%: 50-0 points
|
> 10 => 50 - (feesPercentage - 10) * 5, // 10-20%: 50-0 points
|
||||||
_ => 100 - feesPercentage * 25 // 0-2%: 100-50 points
|
_ => 100 - feesPercentage * 5 // 0-10%: 100-50 points
|
||||||
};
|
};
|
||||||
|
|
||||||
return feeEfficiency;
|
return feeEfficiency;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double CalculateRiskAdjustedReturnScore(double totalPnL, decimal maxDrawdown, decimal initialBalance, BacktestScoringResult result)
|
private static double CalculateRiskAdjustedReturnScore(double totalPnL, decimal maxDrawdown, decimal tradingBalance, BacktestScoringResult result)
|
||||||
{
|
{
|
||||||
if (initialBalance <= 0 || maxDrawdown <= 0) return 0;
|
if (tradingBalance <= 0 || maxDrawdown <= 0) return 0;
|
||||||
|
|
||||||
var pnlRatio = totalPnL / (double)maxDrawdown;
|
// Calculate drawdown as percentage of trading balance
|
||||||
|
var drawdownPercentage = (double)(maxDrawdown / tradingBalance * 100);
|
||||||
|
|
||||||
// Score based on PnL to drawdown ratio
|
// Calculate PnL as percentage of trading balance
|
||||||
return pnlRatio switch
|
var pnlPercentage = (double)((decimal)totalPnL / tradingBalance * 100);
|
||||||
|
|
||||||
|
// Score based on PnL percentage vs drawdown percentage ratio
|
||||||
|
var riskRewardRatio = pnlPercentage / drawdownPercentage;
|
||||||
|
|
||||||
|
// Score based on risk-adjusted return (PnL vs Drawdown based on trading balance)
|
||||||
|
return riskRewardRatio switch
|
||||||
{
|
{
|
||||||
> 3 => 100, // Excellent risk-adjusted return (>3:1)
|
> 3 => 100, // Excellent risk-adjusted return (>3:1)
|
||||||
> 2 => 80 + (pnlRatio - 2) * 20, // 2-3:1: 80-100 points
|
> 2 => 80 + (riskRewardRatio - 2) * 20, // 2-3:1: 80-100 points
|
||||||
> 1.5 => 60 + (pnlRatio - 1.5) * 40, // 1.5-2:1: 60-80 points
|
> 1.5 => 60 + (riskRewardRatio - 1.5) * 40, // 1.5-2:1: 60-80 points
|
||||||
> 1 => 40 + (pnlRatio - 1) * 40, // 1-1.5:1: 40-60 points
|
> 1 => 40 + (riskRewardRatio - 1) * 40, // 1-1.5:1: 40-60 points
|
||||||
> 0.5 => 20 + (pnlRatio - 0.5) * 40, // 0.5-1:1: 20-40 points
|
> 0.5 => 20 + (riskRewardRatio - 0.5) * 40, // 0.5-1:1: 20-40 points
|
||||||
_ => Math.Max(0, pnlRatio * 40) // 0-0.5:1: 0-20 points
|
_ => Math.Max(0, riskRewardRatio * 40) // 0-0.5:1: 0-20 points
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user