Add test and max collateral used
This commit is contained in:
@@ -655,6 +655,51 @@ public class TradingBotCalculationsTests : TradingBoxTests
|
||||
|
||||
#endregion
|
||||
|
||||
#region CalculateROI Tests
|
||||
|
||||
[Fact]
|
||||
public void CalculateROI_WithRealTradingBotData_ReturnsCorrectROI()
|
||||
{
|
||||
// Arrange - Using real trading bot data from the provided JSON
|
||||
var initialBalance = 50m;
|
||||
var netPnL = 4.57691m; // finalBalance - initialBalance = 54.57691 - 50
|
||||
|
||||
// Act - Using existing GetGrowthFromInitalBalance method
|
||||
var result = TradingBox.GetGrowthFromInitalBalance(initialBalance, netPnL);
|
||||
|
||||
// Assert
|
||||
// ROI = (Final - Initial) / Initial * 100 = (54.57691 - 50) / 50 * 100 = 9.15382%
|
||||
result.Should().BeApproximately(9.15382m, 0.00001m);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(100.0, 10.0, 10.0)] // 10% gain: initial=100, netPnL=10, expected=10%
|
||||
[InlineData(100.0, -10.0, -10.0)] // 10% loss: initial=100, netPnL=-10, expected=-10%
|
||||
[InlineData(100.0, 0.0, 0.0)] // No change: initial=100, netPnL=0, expected=0%
|
||||
[InlineData(50.0, 4.57691, 9.15382)] // Real bot data: initial=50, netPnL=4.57691, expected=9.15382%
|
||||
public void CalculateROI_WithVariousInputs_ReturnsCorrectPercentage(decimal initialBalance, decimal netPnL, decimal expectedROI)
|
||||
{
|
||||
// Act
|
||||
var result = TradingBox.GetGrowthFromInitalBalance(initialBalance, netPnL);
|
||||
|
||||
// Assert
|
||||
result.Should().BeApproximately(expectedROI, 0.00001m);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CalculateROI_WithZeroInitialBalance_ThrowsDivideByZeroException()
|
||||
{
|
||||
// Arrange
|
||||
var initialBalance = 0m;
|
||||
var netPnL = 100m;
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<DivideByZeroException>(() =>
|
||||
TradingBox.GetGrowthFromInitalBalance(initialBalance, netPnL));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
private List<Position> CreateLossPositions(int count, TradeDirection direction = TradeDirection.Long)
|
||||
@@ -733,5 +778,118 @@ public class TradingBotCalculationsTests : TradingBoxTests
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CalculateAgentSummaryMetrics Tests
|
||||
|
||||
[Fact]
|
||||
public void CalculateAgentSummaryMetrics_WithRealTradingBotPositions_ReturnsCorrectMetrics()
|
||||
{
|
||||
// Arrange - Create positions based on the real trading bot JSON data
|
||||
var positions = new List<Position>
|
||||
{
|
||||
CreateRealPosition(
|
||||
direction: TradeDirection.Short,
|
||||
openPrice: 2.1849m,
|
||||
quantity: 22.91465209m,
|
||||
leverage: 5m,
|
||||
takeProfitPrice: 2.1602m,
|
||||
realizedPnL: 2.66162442m,
|
||||
netPnL: 2.38787384m,
|
||||
gasFees: 0.15m
|
||||
),
|
||||
CreateRealPosition(
|
||||
direction: TradeDirection.Long,
|
||||
openPrice: 2.104m,
|
||||
quantity: 24.69722156m,
|
||||
leverage: 5m,
|
||||
takeProfitPrice: 2.127m,
|
||||
realizedPnL: 2.71702395m,
|
||||
netPnL: 2.43569648m,
|
||||
gasFees: 0.15m
|
||||
)
|
||||
};
|
||||
|
||||
// Act
|
||||
var metrics = TradingBox.CalculateAgentSummaryMetrics(positions);
|
||||
|
||||
// Assert
|
||||
// Total PnL: 2.66162442 + 2.71702395 = 5.37864837
|
||||
metrics.TotalPnL.Should().BeApproximately(5.37864837m, 0.00000001m);
|
||||
|
||||
// Total Fees: 2 positions * 0.15 gas fees = 0.3 (no UI fees since positions are closed)
|
||||
metrics.TotalFees.Should().Be(0.3m);
|
||||
|
||||
// Net PnL: 5.37864837 - 0.3 = 5.07864837
|
||||
metrics.NetPnL.Should().BeApproximately(5.07864837m, 0.00000001m);
|
||||
|
||||
// Wins: 2, Losses: 0
|
||||
metrics.Wins.Should().Be(2);
|
||||
metrics.Losses.Should().Be(0);
|
||||
|
||||
// Collateral: max of (openPrice * quantity) = max(2.1849 * 22.91465209, 2.104 * 24.69722156)
|
||||
// = max(50.083, 51.96295416224) = 51.96295416224
|
||||
metrics.Collateral.Should().BeApproximately(51.96295416224m, 0.00000000001m);
|
||||
|
||||
// ROI: (netPnL / collateral) * 100 = (5.07864837 / 51.96295416224) * 100 ≈ 9.774%
|
||||
metrics.TotalROI.Should().BeApproximately(9.774m, 0.001m);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static Position CreateRealPosition(
|
||||
TradeDirection direction,
|
||||
decimal openPrice,
|
||||
decimal quantity,
|
||||
decimal leverage,
|
||||
decimal takeProfitPrice,
|
||||
decimal realizedPnL,
|
||||
decimal netPnL,
|
||||
decimal gasFees)
|
||||
{
|
||||
// Create position using the existing test helper
|
||||
var position = CreateTestPosition(
|
||||
openPrice: openPrice,
|
||||
quantity: quantity,
|
||||
direction: direction,
|
||||
leverage: leverage,
|
||||
positionStatus: PositionStatus.Finished,
|
||||
includeTrades: true
|
||||
);
|
||||
|
||||
// Override ticker to XRP
|
||||
position.Ticker = Ticker.XRP;
|
||||
|
||||
// Update trades to match real data
|
||||
position.Open.TradeType = TradeType.Limit;
|
||||
position.Open.Ticker = Ticker.XRP;
|
||||
position.Open.ExchangeOrderId = Guid.NewGuid().ToString();
|
||||
|
||||
// Set TakeProfit1 to filled with the correct price
|
||||
position.TakeProfit1.Status = TradeStatus.Filled;
|
||||
position.TakeProfit1.Date = TestDate.AddHours(1);
|
||||
position.TakeProfit1.Ticker = Ticker.XRP;
|
||||
position.TakeProfit1.Price = takeProfitPrice;
|
||||
position.TakeProfit1.ExchangeOrderId = Guid.NewGuid().ToString();
|
||||
position.TakeProfit1.Message = "EmptyTrade";
|
||||
|
||||
// Set StopLoss to cancelled
|
||||
position.StopLoss.Status = TradeStatus.Cancelled;
|
||||
position.StopLoss.Ticker = Ticker.XRP;
|
||||
position.StopLoss.ExchangeOrderId = Guid.NewGuid().ToString();
|
||||
position.StopLoss.Message = "EmptyTrade";
|
||||
|
||||
// Set Profit and Loss
|
||||
position.ProfitAndLoss = new ProfitAndLoss
|
||||
{
|
||||
Realized = realizedPnL,
|
||||
Net = netPnL
|
||||
};
|
||||
|
||||
// Set fees
|
||||
position.UiFees = 0;
|
||||
position.GasFees = gasFees;
|
||||
|
||||
return position;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -601,7 +601,7 @@ public static class TradingBox
|
||||
var totalVolume = GetTotalVolumeTraded(validPositions);
|
||||
var wins = validPositions.Count(p => (p.ProfitAndLoss?.Net ?? 0m) > 0m);
|
||||
var losses = validPositions.Count(p => (p.ProfitAndLoss?.Net ?? 0m) <= 0m);
|
||||
var collateral = validPositions.Sum(p => (p.Open?.Price ?? 0m) * (p.Open?.Quantity ?? 0m));
|
||||
var collateral = validPositions.Max(p => (p.Open?.Price ?? 0m) * (p.Open?.Quantity ?? 0m));
|
||||
var totalROI = collateral > 0m ? (netPnL / collateral) * 100m : 0m;
|
||||
|
||||
return new AgentSummaryMetrics(totalPnL, netPnL, totalROI, totalVolume, wins, losses, totalFees,
|
||||
|
||||
Reference in New Issue
Block a user