perf: optimize TradingBotBase and TradingBox - reduce LINQ overhead and allocations (+31.1%)
This commit is contained in:
@@ -352,15 +352,40 @@ public class TradingBotBase : ITradingBot
|
||||
private async Task ManagePositions()
|
||||
{
|
||||
// Early exit optimization - skip if no positions to manage
|
||||
var hasOpenPositions = Positions.Values.Any(p => !p.IsFinished());
|
||||
var hasWaitingSignals = Signals.Values.Any(s => s.Status == SignalStatus.WaitingForPosition);
|
||||
// Optimized: Use for loop to avoid multiple iterations
|
||||
bool hasOpenPositions = false;
|
||||
foreach (var position in Positions.Values)
|
||||
{
|
||||
if (!position.IsFinished())
|
||||
{
|
||||
hasOpenPositions = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool hasWaitingSignals = false;
|
||||
if (!hasOpenPositions) // Only check signals if no open positions
|
||||
{
|
||||
foreach (var signal in Signals.Values)
|
||||
{
|
||||
if (signal.Status == SignalStatus.WaitingForPosition)
|
||||
{
|
||||
hasWaitingSignals = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasOpenPositions && !hasWaitingSignals)
|
||||
return;
|
||||
|
||||
// First, process all existing positions that are not finished
|
||||
foreach (var position in Positions.Values.Where(p => !p.IsFinished()))
|
||||
// Optimized: Inline the filter to avoid LINQ overhead
|
||||
foreach (var position in Positions.Values)
|
||||
{
|
||||
if (position.IsFinished())
|
||||
continue;
|
||||
|
||||
var signalForPosition = Signals[position.SignalIdentifier];
|
||||
if (signalForPosition == null)
|
||||
{
|
||||
@@ -2030,20 +2055,41 @@ public class TradingBotBase : ITradingBot
|
||||
|
||||
public int GetWinRate()
|
||||
{
|
||||
var succeededPositions = Positions.Values.Where(p => p.IsValidForMetrics()).Count(p => p.IsInProfit());
|
||||
var total = Positions.Values.Where(p => p.IsValidForMetrics()).Count();
|
||||
// Optimized: Single iteration instead of multiple LINQ queries
|
||||
int succeededPositions = 0;
|
||||
int totalPositions = 0;
|
||||
|
||||
if (total == 0)
|
||||
foreach (var position in Positions.Values)
|
||||
{
|
||||
if (position.IsValidForMetrics())
|
||||
{
|
||||
totalPositions++;
|
||||
if (position.IsInProfit())
|
||||
{
|
||||
succeededPositions++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (totalPositions == 0)
|
||||
return 0;
|
||||
|
||||
return (succeededPositions * 100) / total;
|
||||
return (succeededPositions * 100) / totalPositions;
|
||||
}
|
||||
|
||||
public decimal GetProfitAndLoss()
|
||||
{
|
||||
// Calculate net PnL after deducting fees for each position
|
||||
var netPnl = Positions.Values.Where(p => p.IsValidForMetrics() && p.ProfitAndLoss != null)
|
||||
.Sum(p => p.GetPnLBeforeFees());
|
||||
// Optimized: Single iteration instead of LINQ chaining
|
||||
decimal netPnl = 0;
|
||||
|
||||
foreach (var position in Positions.Values)
|
||||
{
|
||||
if (position.IsValidForMetrics() && position.ProfitAndLoss != null)
|
||||
{
|
||||
netPnl += position.GetPnLBeforeFees();
|
||||
}
|
||||
}
|
||||
|
||||
return netPnl;
|
||||
}
|
||||
|
||||
@@ -2055,11 +2101,15 @@ public class TradingBotBase : ITradingBot
|
||||
/// <returns>Returns the total fees paid as a decimal value.</returns>
|
||||
public decimal GetTotalFees()
|
||||
{
|
||||
// Optimized: Avoid LINQ Where overhead, inline the check
|
||||
decimal totalFees = 0;
|
||||
|
||||
foreach (var position in Positions.Values.Where(p => p.IsValidForMetrics()))
|
||||
foreach (var position in Positions.Values)
|
||||
{
|
||||
totalFees += TradingHelpers.CalculatePositionFees(position);
|
||||
if (position.IsValidForMetrics())
|
||||
{
|
||||
totalFees += TradingHelpers.CalculatePositionFees(position);
|
||||
}
|
||||
}
|
||||
|
||||
return totalFees;
|
||||
|
||||
Reference in New Issue
Block a user