From 27a24ca08a98e310b694150c046635f37f0b89d2 Mon Sep 17 00:00:00 2001 From: konard Date: Thu, 11 Sep 2025 12:50:25 +0300 Subject: [PATCH 1/3] Initial commit with task details for issue #200 Adding CLAUDE.md with task information for AI processing. This file will be removed when the task is complete. Issue: https://github.com/linksplatform/Bot/issues/200 --- CLAUDE.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..48777aa5 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,5 @@ +Issue to solve: https://github.com/linksplatform/Bot/issues/200 +Your prepared branch: issue-200-bfd7e535 +Your prepared working directory: /tmp/gh-issue-solver-1757584218652 + +Proceed. \ No newline at end of file From 6c3707655a1929c4c5f5f9dd381044506180db4a Mon Sep 17 00:00:00 2001 From: konard Date: Thu, 11 Sep 2025 12:50:46 +0300 Subject: [PATCH 2/3] Remove CLAUDE.md - PR created successfully --- CLAUDE.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 48777aa5..00000000 --- a/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -Issue to solve: https://github.com/linksplatform/Bot/issues/200 -Your prepared branch: issue-200-bfd7e535 -Your prepared working directory: /tmp/gh-issue-solver-1757584218652 - -Proceed. \ No newline at end of file From 73104e6aec9662ec169d6f4af5f903f9bfde2be3 Mon Sep 17 00:00:00 2001 From: konard Date: Thu, 11 Sep 2025 12:59:36 +0300 Subject: [PATCH 3/3] Add comprehensive loss detection logging to trader bot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Enhanced GetMinimumSellPrice() with loss detection warnings when MinimumProfitSteps < 0 - Added profit/loss logging when placing sell orders to detect loss scenarios - Added early sell loss detection with clear warnings when selling at top bid results in loss - Added price change loss detection when sell order prices are adjusted downward - Added realized profit/loss tracking in UpdateCashBalance() for executed sell trades - All loss scenarios now logged with LogWarning level for easy detection and investigation - Profit scenarios logged with LogInformation level for comparison - Each log message includes source price, target price, actual loss/profit amount, and lot quantity This allows careful investigation of loss reasons as requested in issue #200. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- csharp/TraderBot/TradingService.cs | 62 +++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/csharp/TraderBot/TradingService.cs b/csharp/TraderBot/TradingService.cs index 0302809b..52cc422c 100644 --- a/csharp/TraderBot/TradingService.cs +++ b/csharp/TraderBot/TradingService.cs @@ -147,10 +147,29 @@ protected void UpdateCashBalance(OrderTrades orderTrades) if(orderTrades.Direction == OrderDirection.Buy) { SetCashBalance(CashBalanceFree, CashBalanceLocked - cashBalanceDelta); + Logger.LogInformation($"Buy execution: {trade.Quantity} lots at {trade.Price}, total cost: {cashBalanceDelta}"); } else if (orderTrades.Direction == OrderDirection.Sell) { SetCashBalance(CashBalanceFree + cashBalanceDelta, CashBalanceLocked); + + // Track realized profit/loss for sell trades + if (ActiveSellOrderSourcePrice.TryGetValue(orderTrades.OrderId, out var sourcePrice)) + { + var realizedProfitLoss = (trade.Price - sourcePrice) * trade.Quantity; + if (realizedProfitLoss < 0) + { + Logger.LogWarning($"Loss realized: SELL EXECUTED at LOSS. Source price: {sourcePrice}, execution price: {trade.Price}, lots: {trade.Quantity}, realized loss: {Math.Abs(realizedProfitLoss)}, total revenue: {cashBalanceDelta}"); + } + else + { + Logger.LogInformation($"Profit realized: sell executed at profit. Source price: {sourcePrice}, execution price: {trade.Price}, lots: {trade.Quantity}, realized profit: {realizedProfitLoss}, total revenue: {cashBalanceDelta}"); + } + } + else + { + Logger.LogInformation($"Sell execution: {trade.Quantity} lots at {trade.Price}, total revenue: {cashBalanceDelta} (source price not tracked)"); + } } } } @@ -461,6 +480,17 @@ await marketDataStream.RequestStream.WriteAsync(new MarketDataRequest var targetSellPrice = GetTargetSellPrice(minimumSellPrice, bestAsk); var marketLotsAtTargetPrice = orderBook.Asks.FirstOrDefault(o => o.Price == targetSellPrice)?.Quantity ?? 0; Logger.LogInformation($"marketLotsAtTargetPrice: {marketLotsAtTargetPrice}"); + + var actualProfitLoss = targetSellPrice - maxPrice; + if (actualProfitLoss < 0) + { + Logger.LogWarning($"Loss detection: placing sell order at LOSS. Source price: {maxPrice}, target sell price: {targetSellPrice}, actual loss: {Math.Abs(actualProfitLoss)}, lots: {totalAmount}"); + } + else + { + Logger.LogInformation($"Profit tracking: placing sell order at profit. Source price: {maxPrice}, target sell price: {targetSellPrice}, profit: {actualProfitLoss}, lots: {totalAmount}"); + } + var response = await PlaceSellOrder(totalAmount, targetSellPrice); ActiveSellOrderSourcePrice[response.OrderId] = maxPrice; Logger.LogInformation($"sell complete"); @@ -611,6 +641,15 @@ await marketDataStream.RequestStream.WriteAsync(new MarketDataRequest continue; } // Place new order at top bid price + var earlySellProfitLoss = topBid - sourcePrice; + if (earlySellProfitLoss < 0) + { + Logger.LogWarning($"Loss detection: EARLY SELL at LOSS. Source price: {sourcePrice}, top bid price: {topBid}, actual loss: {Math.Abs(earlySellProfitLoss)}, lots: {activeSellOrder.LotsRequested}"); + } + else + { + Logger.LogInformation($"Early sell profit tracking: source price: {sourcePrice}, top bid price: {topBid}, profit: {earlySellProfitLoss}, lots: {activeSellOrder.LotsRequested}"); + } var response = await PlaceSellOrder(activeSellOrder.LotsRequested, topBid); SyncActiveOrders(); Logger.LogInformation($"early sell is complete"); @@ -636,6 +675,17 @@ await marketDataStream.RequestStream.WriteAsync(new MarketDataRequest var targetSellPrice = GetTargetSellPrice(minimumSellPrice, bestAsk); var marketLotsAtTargetPrice = orderBook.Asks.FirstOrDefault(o => o.Price == targetSellPrice)?.Quantity ?? 0; Logger.LogInformation($"marketLotsAtTargetPrice: {marketLotsAtTargetPrice}"); + + var priceChangeProfitLoss = targetSellPrice - sourcePrice; + if (priceChangeProfitLoss < 0) + { + Logger.LogWarning($"Loss detection: PRICE CHANGE to LOSS position. Source price: {sourcePrice}, new target price: {targetSellPrice}, actual loss: {Math.Abs(priceChangeProfitLoss)}, lots: {activeSellOrder.LotsRequested}"); + } + else + { + Logger.LogInformation($"Price change profit tracking: source price: {sourcePrice}, new target price: {targetSellPrice}, profit: {priceChangeProfitLoss}, lots: {activeSellOrder.LotsRequested}"); + } + var response = await PlaceSellOrder(activeSellOrder.LotsRequested, targetSellPrice); ActiveSellOrderSourcePrice[response.OrderId] = sourcePrice; SyncActiveOrders(); @@ -680,7 +730,17 @@ private void SetCashBalance(decimal free, decimal locked) private decimal GetMinimumSellPrice(decimal sourcePrice) { var minimumSellPrice = sourcePrice + Settings.MinimumProfitSteps * PriceStep; - // Logger.LogInformation($"minimumSellPrice: {minimumSellPrice}"); + var profitLoss = minimumSellPrice - sourcePrice; + + if (Settings.MinimumProfitSteps < 0) + { + Logger.LogWarning($"Loss detection: selling at loss allowed. Source price: {sourcePrice}, minimum sell price: {minimumSellPrice}, potential loss: {Math.Abs(profitLoss)} ({Settings.MinimumProfitSteps} price steps)"); + } + else + { + Logger.LogInformation($"Profit calculation: source price: {sourcePrice}, minimum sell price: {minimumSellPrice}, minimum profit: {profitLoss} ({Settings.MinimumProfitSteps} price steps)"); + } + return minimumSellPrice; }