Remove orderBy to improve perfs
This commit is contained in:
@@ -82,16 +82,16 @@ public static class TradingBox
|
||||
// Validate required parameters
|
||||
if (lightScenario == null)
|
||||
throw new ArgumentNullException(nameof(lightScenario), "Scenario cannot be null");
|
||||
|
||||
|
||||
if (newCandles == null)
|
||||
throw new ArgumentNullException(nameof(newCandles), "Candles cannot be null");
|
||||
|
||||
|
||||
// Empty candles or no indicators is a valid business case - return null
|
||||
if (!newCandles.Any() || lightScenario.Indicators == null || !lightScenario.Indicators.Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
var signalOnCandles = new List<LightSignal>();
|
||||
|
||||
foreach (var indicator in lightScenario.Indicators)
|
||||
@@ -189,19 +189,19 @@ public static class TradingBox
|
||||
{
|
||||
// Only one strategy, return the single signal if it meets minimum confidence
|
||||
var signal = signalOnCandles.Single();
|
||||
|
||||
|
||||
// Check if signal meets minimum confidence threshold
|
||||
// None confidence should always be rejected regardless of threshold
|
||||
if (signal.Confidence == Confidence.None || signal.Confidence < config.MinimumConfidence)
|
||||
{
|
||||
return null; // Below minimum confidence threshold or None
|
||||
}
|
||||
|
||||
|
||||
return signal;
|
||||
}
|
||||
|
||||
// Optimized: Sort only if needed, then convert to HashSet
|
||||
var orderedSignals = signalOnCandles.OrderBy(s => s.Date).ToList();
|
||||
var orderedSignals = signalOnCandles.ToList();
|
||||
signalOnCandles = new HashSet<LightSignal>(orderedSignals);
|
||||
|
||||
// Check if all strategies produced signals - this is required for composite signals
|
||||
@@ -246,7 +246,8 @@ public static class TradingBox
|
||||
// Calculate confidence based on the average confidence of all signals
|
||||
var averageConfidence = CalculateAverageConfidence(allDirectionalSignals);
|
||||
|
||||
if (finalDirection == TradeDirection.None || averageConfidence == Confidence.None || averageConfidence < config.MinimumConfidence)
|
||||
if (finalDirection == TradeDirection.None || averageConfidence == Confidence.None ||
|
||||
averageConfidence < config.MinimumConfidence)
|
||||
{
|
||||
return null; // No valid signal, None confidence, or below minimum confidence
|
||||
}
|
||||
@@ -465,12 +466,13 @@ public static class TradingBox
|
||||
{
|
||||
var stopLoss = 0M;
|
||||
var takeProfit = 0M;
|
||||
|
||||
|
||||
// Filter candles after the position's opening trade was filled, up to the next position
|
||||
var candlesBeforeNextPosition = candles.Where(c =>
|
||||
c.Date >= position.Open.Date && c.Date <= (nextPosition == null ? candles.Last().Date : nextPosition.Open.Date))
|
||||
c.Date >= position.Open.Date &&
|
||||
c.Date <= (nextPosition == null ? candles.Last().Date : nextPosition.Open.Date))
|
||||
.ToList();
|
||||
|
||||
|
||||
// If no candles after position opened, return zeros
|
||||
if (!candlesBeforeNextPosition.Any())
|
||||
{
|
||||
@@ -585,8 +587,8 @@ public static class TradingBox
|
||||
public static AgentSummaryMetrics CalculateAgentSummaryMetrics(List<Position> positions)
|
||||
{
|
||||
var validPositions = positions?
|
||||
.Where(p => p.IsValidForMetrics())
|
||||
.ToList() ?? new List<Position>();
|
||||
.Where(p => p.IsValidForMetrics())
|
||||
.ToList() ?? new List<Position>();
|
||||
|
||||
if (!validPositions.Any())
|
||||
{
|
||||
@@ -613,7 +615,8 @@ public static class TradingBox
|
||||
/// <param name="positions">List of all positions to analyze</param>
|
||||
/// <param name="previousTotalVolume">Previous total volume to ensure cumulative volume never decreases</param>
|
||||
/// <returns>PlatformSummaryMetrics with all calculated values</returns>
|
||||
public static PlatformSummaryMetrics CalculatePlatformSummaryMetrics(List<Position> positions, decimal previousTotalVolume = 0m)
|
||||
public static PlatformSummaryMetrics CalculatePlatformSummaryMetrics(List<Position> positions,
|
||||
decimal previousTotalVolume = 0m)
|
||||
{
|
||||
if (positions == null || !positions.Any())
|
||||
{
|
||||
@@ -660,12 +663,14 @@ public static class TradingBox
|
||||
|
||||
if (position.TakeProfit1?.Status == TradeStatus.Filled)
|
||||
{
|
||||
closingVolume += position.TakeProfit1.Price * position.TakeProfit1.Quantity * position.TakeProfit1.Leverage;
|
||||
closingVolume += position.TakeProfit1.Price * position.TakeProfit1.Quantity *
|
||||
position.TakeProfit1.Leverage;
|
||||
}
|
||||
|
||||
if (position.TakeProfit2?.Status == TradeStatus.Filled)
|
||||
{
|
||||
closingVolume += position.TakeProfit2.Price * position.TakeProfit2.Quantity * position.TakeProfit2.Leverage;
|
||||
closingVolume += position.TakeProfit2.Price * position.TakeProfit2.Quantity *
|
||||
position.TakeProfit2.Leverage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -683,6 +688,7 @@ public static class TradingBox
|
||||
{
|
||||
volumeByAsset[ticker] = 0;
|
||||
}
|
||||
|
||||
volumeByAsset[ticker] += positionVolume;
|
||||
|
||||
// Position count breakdown by asset - update state directly
|
||||
@@ -690,6 +696,7 @@ public static class TradingBox
|
||||
{
|
||||
positionCountByAsset[ticker] = 0;
|
||||
}
|
||||
|
||||
positionCountByAsset[ticker]++;
|
||||
|
||||
// Calculate fees and PnL for all positions
|
||||
@@ -709,6 +716,7 @@ public static class TradingBox
|
||||
{
|
||||
positionCountByDirection[direction] = 0;
|
||||
}
|
||||
|
||||
positionCountByDirection[direction]++;
|
||||
}
|
||||
}
|
||||
@@ -1183,10 +1191,11 @@ public static class TradingBox
|
||||
/// <param name="leverage">The leverage multiplier</param>
|
||||
/// <param name="direction">The trade direction (Long or Short)</param>
|
||||
/// <returns>The calculated PnL</returns>
|
||||
public static decimal CalculatePnL(decimal entryPrice, decimal exitPrice, decimal quantity, decimal leverage, TradeDirection direction)
|
||||
public static decimal CalculatePnL(decimal entryPrice, decimal exitPrice, decimal quantity, decimal leverage,
|
||||
TradeDirection direction)
|
||||
{
|
||||
var positionSize = CalculatePositionSize(quantity, leverage);
|
||||
|
||||
|
||||
if (direction == TradeDirection.Long)
|
||||
{
|
||||
return (exitPrice - entryPrice) * positionSize;
|
||||
@@ -1301,7 +1310,8 @@ public static class TradingBox
|
||||
/// <param name="maxLossStreak">Maximum allowed loss streak (0 or negative means no limit)</param>
|
||||
/// <param name="signalDirection">The direction of the signal for the new position</param>
|
||||
/// <returns>True if position can be opened, false if blocked by loss streak</returns>
|
||||
public static bool CheckLossStreak(List<Position> recentPositions, int maxLossStreak, TradeDirection signalDirection)
|
||||
public static bool CheckLossStreak(List<Position> recentPositions, int maxLossStreak,
|
||||
TradeDirection signalDirection)
|
||||
{
|
||||
// If MaxLossStreak is 0, there's no limit
|
||||
if (maxLossStreak <= 0)
|
||||
|
||||
Reference in New Issue
Block a user