Add more tests + Log pnl for each backtest
This commit is contained in:
@@ -812,17 +812,11 @@ public class TradingBotBase : ITradingBot
|
||||
|
||||
var currentTime = Config.IsForBacktest ? lastCandle.Date : DateTime.UtcNow;
|
||||
var currentPnl = positionForSignal.ProfitAndLoss?.Net ?? 0;
|
||||
var pnlPercentage = positionForSignal.Open.Price * positionForSignal.Open.Quantity != 0
|
||||
? Math.Round((currentPnl / (positionForSignal.Open.Price * positionForSignal.Open.Quantity)) * 100,
|
||||
2)
|
||||
: 0;
|
||||
var pnlPercentage = TradingBox.CalculatePnLPercentage(currentPnl, positionForSignal.Open.Price, positionForSignal.Open.Quantity);
|
||||
|
||||
var isPositionInProfit = positionForSignal.OriginDirection == TradeDirection.Long
|
||||
? lastCandle.Close > positionForSignal.Open.Price
|
||||
: lastCandle.Close < positionForSignal.Open.Price;
|
||||
var isPositionInProfit = TradingBox.IsPositionInProfit(positionForSignal.Open.Price, lastCandle.Close, positionForSignal.OriginDirection);
|
||||
|
||||
var hasExceededTimeLimit = Config.MaxPositionTimeHours.HasValue &&
|
||||
HasPositionExceededTimeLimit(positionForSignal, currentTime);
|
||||
var hasExceededTimeLimit = TradingBox.HasPositionExceededTimeLimit(positionForSignal.Open.Date, currentTime, Config.MaxPositionTimeHours);
|
||||
|
||||
if (hasExceededTimeLimit)
|
||||
{
|
||||
@@ -1246,29 +1240,16 @@ public class TradingBotBase : ITradingBot
|
||||
.Take(Config.MaxLossStreak)
|
||||
.ToList();
|
||||
|
||||
// If we don't have enough positions to form a streak, we can open
|
||||
if (recentPositions.Count < Config.MaxLossStreak)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if all recent positions were losses
|
||||
var allLosses = recentPositions.All(p => p.ProfitAndLoss?.Realized < 0);
|
||||
if (!allLosses)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we have a loss streak, check if the last position was in the same direction as the signal
|
||||
var lastPosition = recentPositions.First();
|
||||
if (lastPosition.OriginDirection == signal.Direction)
|
||||
var canOpen = TradingBox.CheckLossStreak(recentPositions, Config.MaxLossStreak, signal.Direction);
|
||||
|
||||
if (!canOpen)
|
||||
{
|
||||
var lastPosition = recentPositions.First();
|
||||
await LogWarning(
|
||||
$"🔥 Loss Streak Limit\nCannot open position\nMax loss streak: `{Config.MaxLossStreak}` reached\n📉 Last `{recentPositions.Count}` trades were losses\n🎯 Last position: `{lastPosition.OriginDirection}`\nWaiting for opposite direction signal");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return canOpen;
|
||||
}
|
||||
|
||||
private async Task<bool> CheckBrokerPositions()
|
||||
@@ -1869,17 +1850,9 @@ public class TradingBotBase : ITradingBot
|
||||
if (pnlCalculated && closingPrice > 0)
|
||||
{
|
||||
var entryPrice = position.Open.Price;
|
||||
var positionSize = position.Open.Quantity * position.Open.Leverage;
|
||||
var positionSize = TradingBox.CalculatePositionSize(position.Open.Quantity, position.Open.Leverage);
|
||||
|
||||
decimal pnl;
|
||||
if (position.OriginDirection == TradeDirection.Long)
|
||||
{
|
||||
pnl = (closingPrice - entryPrice) * positionSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
pnl = (entryPrice - closingPrice) * positionSize;
|
||||
}
|
||||
decimal pnl = TradingBox.CalculatePnL(entryPrice, closingPrice, position.Open.Quantity, position.Open.Leverage, position.OriginDirection);
|
||||
|
||||
if (position.ProfitAndLoss == null)
|
||||
{
|
||||
@@ -1901,7 +1874,7 @@ public class TradingBotBase : ITradingBot
|
||||
$"Entry Price: `${entryPrice:F2}` | Exit Price: `${closingPrice:F2}`\n" +
|
||||
$"Position Size: `{position.Open.Quantity:F8}` | Leverage: `{position.Open.Leverage}x`\n" +
|
||||
$"Position Value: `${positionSize:F8}`\n" +
|
||||
$"Price Difference: `${(position.OriginDirection == TradeDirection.Long ? closingPrice - entryPrice : entryPrice - closingPrice):F2}`\n" +
|
||||
$"Price Difference: `${TradingBox.CalculatePriceDifference(entryPrice, closingPrice, position.OriginDirection):F2}`\n" +
|
||||
$"Realized P&L: `${pnl:F2}`\n" +
|
||||
$"Gas Fees: `${position.GasFees:F2}` | UI Fees: `${position.UiFees:F2}`\n" +
|
||||
$"Total Fees: `${position.GasFees + position.UiFees:F2}`\n" +
|
||||
@@ -2308,18 +2281,6 @@ public class TradingBotBase : ITradingBot
|
||||
/// <param name="position">The position to check</param>
|
||||
/// <param name="currentTime">The current time to compare against</param>
|
||||
/// <returns>True if the position has exceeded the time limit, false otherwise</returns>
|
||||
private bool HasPositionExceededTimeLimit(Position position, DateTime currentTime)
|
||||
{
|
||||
if (!Config.MaxPositionTimeHours.HasValue || Config.MaxPositionTimeHours.Value <= 0)
|
||||
{
|
||||
return false; // Time-based closure is disabled
|
||||
}
|
||||
|
||||
var timeOpen = currentTime - position.Open.Date;
|
||||
var maxTimeAllowed = TimeSpan.FromHours((double)Config.MaxPositionTimeHours.Value);
|
||||
|
||||
return timeOpen >= maxTimeAllowed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the trading bot configuration with new settings.
|
||||
@@ -2630,8 +2591,7 @@ public class TradingBotBase : ITradingBot
|
||||
}
|
||||
|
||||
// Calculate cooldown end time based on last position closing time
|
||||
var baseIntervalSeconds = CandleHelpers.GetBaseIntervalInSeconds(Config.Timeframe);
|
||||
var cooldownEndTime = LastPositionClosingTime.Value.AddSeconds(baseIntervalSeconds * Config.CooldownPeriod);
|
||||
var cooldownEndTime = TradingBox.CalculateCooldownEndTime(LastPositionClosingTime.Value, Config.Timeframe, Config.CooldownPeriod);
|
||||
var isInCooldown = (Config.IsForBacktest ? LastCandle.Date : DateTime.UtcNow) < cooldownEndTime;
|
||||
|
||||
if (isInCooldown)
|
||||
|
||||
Reference in New Issue
Block a user