Update messaging

This commit is contained in:
2025-10-06 01:34:13 +07:00
parent dab4807334
commit 347c78afc7
8 changed files with 144 additions and 171 deletions

View File

@@ -82,16 +82,16 @@ public class TradingBotBase : ITradingBot
{
case BotStatus.Saved:
var indicatorNames = Config.Scenario.Indicators.Select(i => i.Type.ToString()).ToList();
var startupMessage = $"🚀 **Bot Started Successfully!**\n\n" +
$"📊 **Trading Setup:**\n" +
var startupMessage = $"🚀 Bot Started Successfully\n\n" +
$"📊 Trading Setup:\n" +
$"🎯 Ticker: `{Config.Ticker}`\n" +
$"⏰ Timeframe: `{Config.Timeframe}`\n" +
$"🎮 Scenario: `{Config.Scenario?.Name ?? "Unknown"}`\n" +
$"💰 Balance: `${Config.BotTradingBalance:F2}`\n" +
$"👀 Mode: `{(Config.IsForWatchingOnly ? "Watch Only" : "Live Trading")}`\n\n" +
$"📈 **Active Indicators:** `{string.Join(", ", indicatorNames)}`\n\n" +
$"✅ Ready to monitor signals and execute trades!\n" +
$"📢 I'll notify you when signals are triggered.";
$"📈 Active Indicators: `{string.Join(", ", indicatorNames)}`\n\n" +
$"✅ Ready to monitor signals and execute trades\n" +
$"📢 Notifications will be sent when positions are triggered";
await LogInformation(startupMessage);
break;
@@ -101,7 +101,7 @@ public class TradingBotBase : ITradingBot
case BotStatus.Stopped:
// If status was Stopped we log a message to inform the user that the bot is restarting
await LogInformation($"🔄 **Bot Restarted**\n" +
await LogInformation($"🔄 Bot Restarted\n" +
$"📊 Resuming operations with {Signals.Count} signals and {Positions.Count} positions\n" +
$"✅ Ready to continue trading");
break;
@@ -264,7 +264,7 @@ public class TradingBotBase : ITradingBot
Signals.Add(recreatedSignal.Identifier, recreatedSignal);
await LogInformation(
$"🔍 **Signal Recovery Success**\nRecreated signal: `{recreatedSignal.Identifier}`\nFor position: `{position.Identifier}`");
$"🔍 Signal Recovery Success\nRecreated signal: `{recreatedSignal.Identifier}`\nFor position: `{position.Identifier}`");
return recreatedSignal;
}
catch (Exception ex)
@@ -283,7 +283,7 @@ public class TradingBotBase : ITradingBot
if (signalForPosition == null)
{
await LogInformation(
$"🔍 **Signal Recovery**\nSignal not found for position `{position.Identifier}`\nRecreating signal from position data...");
$"🔍 Signal Recovery\nSignal not found for position `{position.Identifier}`\nRecreating signal from position data...");
// Recreate the signal based on position information
signalForPosition = await RecreateSignalFromPosition(position);
@@ -299,7 +299,7 @@ public class TradingBotBase : ITradingBot
if (signalForPosition.Status != SignalStatus.PositionOpen && position.Status != PositionStatus.Finished)
{
await LogInformation(
$"🔄 **Signal Status Update**\nSignal: `{signalForPosition.Identifier}`\nStatus: `{signalForPosition.Status}` → `PositionOpen`");
$"🔄 Signal Status Update\nSignal: `{signalForPosition.Identifier}`\nStatus: `{signalForPosition.Status}` → `PositionOpen`");
SetSignalStatus(signalForPosition.Identifier, SignalStatus.PositionOpen);
}
@@ -315,7 +315,7 @@ public class TradingBotBase : ITradingBot
if (LastCandle != null && signal.Date < LastCandle.Date)
{
await LogWarning(
$"❌ **Signal Expired**\nSignal `{signal.Identifier}` is older than last candle `{LastCandle.Date}`\nStatus: `Expired`");
$"❌ Signal Expired\nSignal `{signal.Identifier}` is older than last candle `{LastCandle.Date}`\nStatus: `Expired`");
SetSignalStatus(signal.Identifier, SignalStatus.Expired);
continue;
}
@@ -327,7 +327,7 @@ public class TradingBotBase : ITradingBot
{
// Position already exists for this signal, update signal status
await LogInformation(
$"🔄 **Signal Status Update**\nSignal: `{signal.Identifier}`\nStatus: `{signal.Status}` → `PositionOpen`\nPosition already exists: `{existingPosition.Identifier}`");
$"🔄 Signal Status Update\nSignal: `{signal.Identifier}`\nStatus: `{signal.Status}` → `PositionOpen`\nPosition already exists: `{existingPosition.Identifier}`");
SetSignalStatus(signal.Identifier, SignalStatus.PositionOpen);
continue;
}
@@ -342,7 +342,7 @@ public class TradingBotBase : ITradingBot
else
{
await LogWarning(
$"⚠️ **Position Creation Failed**\nSignal: `{signal.Identifier}`\nPosition creation returned null");
$"⚠️ Position Creation Failed\nSignal: `{signal.Identifier}`\nPosition creation returned null");
}
}
}
@@ -486,7 +486,7 @@ public class TradingBotBase : ITradingBot
if (timeSinceRequest.TotalMinutes >= waitTimeMinutes)
{
await LogWarning(
$"⚠️ **Order Cleanup**\nToo many open orders: `{orders.Count()}`\nPosition: `{positionForSignal.Identifier}`\nTime elapsed: `{waitTimeMinutes}min`\nCanceling all orders...");
$"⚠️ Order Cleanup\nToo many open orders: `{orders.Count()}`\nPosition: `{positionForSignal.Identifier}`\nTime elapsed: `{waitTimeMinutes}min`\nCanceling all orders...");
try
{
await ServiceScopeHelpers.WithScopedService<IExchangeService>(_scopeFactory,
@@ -495,7 +495,7 @@ public class TradingBotBase : ITradingBot
await exchangeService.CancelOrder(Account, Config.Ticker);
});
await LogInformation(
$"✅ **Orders Canceled**\nSuccessfully canceled all orders for: `{Config.Ticker}`");
$"✅ Orders Canceled\nSuccessfully canceled all orders for: `{Config.Ticker}`");
}
catch (Exception ex)
{
@@ -510,7 +510,7 @@ public class TradingBotBase : ITradingBot
{
var remainingMinutes = waitTimeMinutes - timeSinceRequest.TotalMinutes;
await LogInformation(
$"⏳ **Waiting for Orders**\nPosition has `{orders.Count()}` open orders\nElapsed: `{timeSinceRequest.TotalMinutes:F1}min`\nWaiting `{remainingMinutes:F1}min` more before canceling");
$"⏳ Waiting for Orders\nPosition has `{orders.Count()}` open orders\nElapsed: `{timeSinceRequest.TotalMinutes:F1}min`\nWaiting `{remainingMinutes:F1}min` more before canceling");
}
}
else if (ordersCount == 2)
@@ -518,7 +518,7 @@ public class TradingBotBase : ITradingBot
// TODO: This should never happen, but just in case
// Check if position is already open on broker with 2 orders
await LogInformation(
$"🔍 **Checking Broker Position**\nPosition has exactly `{orders.Count()}` open orders\nChecking if position is already open on broker...");
$"🔍 Checking Broker Position\nPosition has exactly `{orders.Count()}` open orders\nChecking if position is already open on broker...");
Position brokerPosition = null;
await ServiceScopeHelpers.WithScopedService<IExchangeService>(_scopeFactory,
@@ -531,7 +531,7 @@ public class TradingBotBase : ITradingBot
if (brokerPosition != null)
{
await LogInformation(
$"✅ **Position Found on Broker**\nPosition is already open on broker\nUpdating position status to Filled");
$"✅ Position Found on Broker\nPosition is already open on broker\nUpdating position status to Filled");
// Calculate net PnL after fees for broker position
var brokerNetPnL = brokerPosition.GetNetPnL();
@@ -564,19 +564,19 @@ public class TradingBotBase : ITradingBot
else
{
await LogInformation(
$"⏸️ **Position Pending**\nPosition still waiting to open\n`{orders.Count()}` open orders remaining");
$"⏸️ Position Pending\nPosition still waiting to open\n`{orders.Count()}` open orders remaining");
}
}
else
{
await LogInformation(
$"⏸️ **Position Pending**\nPosition still waiting to open\n`{orders.Count()}` open orders remaining");
$"⏸️ Position Pending\nPosition still waiting to open\n`{orders.Count()}` open orders remaining");
}
}
else
{
await LogWarning(
$"❌ **Position Never Filled**\nNo position on exchange and no orders\nSignal: `{signal.Identifier}`\nPosition was never filled and will be marked as canceled.");
$"❌ Position Never Filled\nNo position on exchange and no orders\nSignal: `{signal.Identifier}`\nPosition was never filled and will be marked as canceled.");
// Position was never filled (still in New status), so just mark it as canceled
// Don't call HandleClosedPosition as that would incorrectly add volume/PnL
@@ -622,7 +622,7 @@ public class TradingBotBase : ITradingBot
var profitStatus = isPositionInProfit ? "in profit" : "at a loss";
await LogInformation(
$"⏰ **Time Limit Close**\nClosing position due to time limit: `{Config.MaxPositionTimeHours}h` exceeded\n📈 Position Status: **{profitStatus}**\n💰 Entry: `${positionForSignal.Open.Price}` → Current: `${lastCandle.Close}`\n📊 Realized PNL: `${currentPnl:F2}` (`{pnlPercentage:F2}%`)");
$"⏰ Time Limit Close\nClosing position due to time limit: `{Config.MaxPositionTimeHours}h` exceeded\n📈 Position Status: {profitStatus}\n💰 Entry: `${positionForSignal.Open.Price}` → Current: `${lastCandle.Close}`\n📊 Realized PNL: `${currentPnl:F2}` (`{pnlPercentage:F2}%`)");
await CloseTrade(signal, positionForSignal, positionForSignal.Open, lastCandle.Close, true);
return;
}
@@ -651,7 +651,7 @@ public class TradingBotBase : ITradingBot
}
await LogInformation(
$"🛑 **Stop Loss Hit**\nClosing LONG position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.StopLoss.Price:F2}`)");
$"🛑 Stop Loss Hit\nClosing LONG position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.StopLoss.Price:F2}`)");
await CloseTrade(signal, positionForSignal, positionForSignal.StopLoss,
executionPrice, true);
}
@@ -671,7 +671,7 @@ public class TradingBotBase : ITradingBot
}
await LogInformation(
$"🎯 **Take Profit 1 Hit**\nClosing LONG position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.TakeProfit1.Price:F2}`)");
$"🎯 Take Profit 1 Hit\nClosing LONG position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.TakeProfit1.Price:F2}`)");
await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit1,
executionPrice, positionForSignal.TakeProfit2 == null);
}
@@ -690,7 +690,7 @@ public class TradingBotBase : ITradingBot
}
await LogInformation(
$"🎯 **Take Profit 2 Hit**\nClosing LONG position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.TakeProfit2.Price:F2}`)");
$"🎯 Take Profit 2 Hit\nClosing LONG position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.TakeProfit2.Price:F2}`)");
await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit2,
executionPrice, true);
}
@@ -717,7 +717,7 @@ public class TradingBotBase : ITradingBot
}
await LogInformation(
$"🛑 **Stop Loss Hit**\nClosing SHORT position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.StopLoss.Price:F2}`)");
$"🛑 Stop Loss Hit\nClosing SHORT position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.StopLoss.Price:F2}`)");
await CloseTrade(signal, positionForSignal, positionForSignal.StopLoss,
executionPrice, true);
}
@@ -737,7 +737,7 @@ public class TradingBotBase : ITradingBot
}
await LogInformation(
$"🎯 **Take Profit 1 Hit**\nClosing SHORT position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.TakeProfit1.Price:F2}`)");
$"🎯 Take Profit 1 Hit\nClosing SHORT position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.TakeProfit1.Price:F2}`)");
await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit1,
executionPrice, positionForSignal.TakeProfit2 == null);
}
@@ -756,7 +756,7 @@ public class TradingBotBase : ITradingBot
}
await LogInformation(
$"🎯 **Take Profit 2 Hit**\nClosing SHORT position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.TakeProfit2.Price:F2}`)");
$"🎯 Take Profit 2 Hit\nClosing SHORT position\nPrice: `${executionPrice:F2}` (was `${positionForSignal.TakeProfit2.Price:F2}`)");
await CloseTrade(signal, positionForSignal, positionForSignal.TakeProfit2,
executionPrice, true);
}
@@ -845,7 +845,7 @@ public class TradingBotBase : ITradingBot
if (openedPosition.OriginDirection == signal.Direction)
{
await LogInformation(
$"📍 **Same Direction Signal**\nSignal `{signal.Identifier}` tried to open position\nBut `{previousSignal.Identifier}` already open for same direction");
$"📍 Same Direction Signal\nSignal `{signal.Identifier}` tried to open position\nBut `{previousSignal.Identifier}` already open for same direction");
SetSignalStatus(signal.Identifier, SignalStatus.Expired);
return null;
}
@@ -863,19 +863,19 @@ public class TradingBotBase : ITradingBot
: "FlipOnlyWhenInProfit is disabled";
await LogInformation(
$"🔄 **Position Flip Initiated**\nFlipping position due to opposite signal\nReason: {flipReason}");
$"🔄 Position Flip Initiated\nFlipping position due to opposite signal\nReason: {flipReason}");
await CloseTrade(previousSignal, openedPosition, openedPosition.Open, lastPrice, true);
await SetPositionStatus(previousSignal.Identifier, PositionStatus.Flipped);
var newPosition = await OpenPosition(signal);
await LogInformation(
$"✅ **Position Flipped**\nPosition: `{previousSignal.Identifier}` → `{signal.Identifier}`\nPrice: `${lastPrice}`");
$"✅ Position Flipped\nPosition: `{previousSignal.Identifier}` → `{signal.Identifier}`\nPrice: `${lastPrice}`");
return newPosition;
}
else
{
var currentPnl = openedPosition.ProfitAndLoss?.Realized ?? 0;
await LogInformation(
$"💸 **Flip Blocked - Not Profitable**\nPosition `{previousSignal.Identifier}` PnL: `${currentPnl:F2}`\nSignal `{signal.Identifier}` will wait for profitability");
$"💸 Flip Blocked - Not Profitable\nPosition `{previousSignal.Identifier}` PnL: `${currentPnl:F2}`\nSignal `{signal.Identifier}` will wait for profitability");
SetSignalStatus(signal.Identifier, SignalStatus.Expired);
return null;
@@ -884,7 +884,7 @@ public class TradingBotBase : ITradingBot
else
{
await LogInformation(
$"🚫 **Flip Disabled**\nPosition already open for: `{previousSignal.Identifier}`\nFlipping disabled, new signal expired");
$"🚫 Flip Disabled\nPosition already open for: `{previousSignal.Identifier}`\nFlipping disabled, new signal expired");
SetSignalStatus(signal.Identifier, SignalStatus.Expired);
return null;
}
@@ -899,9 +899,6 @@ public class TradingBotBase : ITradingBot
return null;
}
await LogInformation(
$"🚀 **Opening Position**\nTime: `{signal.Date:HH:mm:ss}`\nSignal: `{signal.Identifier}`");
try
{
var command = new OpenPositionRequest(
@@ -936,7 +933,7 @@ public class TradingBotBase : ITradingBot
if (!Config.IsForBacktest)
{
await ServiceScopeHelpers.WithScopedService<IMessengerService>(_scopeFactory,
async messengerService => { await messengerService.SendPosition(position); });
async messengerService => { await messengerService.SendClosedPosition(position, Account.User); });
}
Logger.LogInformation($"Position requested");
@@ -979,7 +976,7 @@ public class TradingBotBase : ITradingBot
// TODO : check if its a startup cycle
if (!Config.IsForBacktest && ExecutionCount == 0)
{
await LogInformation("⏳ **Bot Not Ready**\nCannot open position\nBot hasn't executed first cycle yet");
await LogInformation("⏳ Bot Not Ready\nCannot open position\nBot hasn't executed first cycle yet");
return false;
}
@@ -1059,7 +1056,7 @@ public class TradingBotBase : ITradingBot
if (lastPosition.OriginDirection == signal.Direction)
{
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");
$"🔥 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;
}
@@ -1104,7 +1101,7 @@ public class TradingBotBase : ITradingBot
}
catch (Exception ex)
{
await LogWarning($"❌ **Broker Position Check Failed**\nError checking broker positions\n{ex.Message}");
await LogWarning($"❌ Broker Position Check Failed\nError checking broker positions\n{ex.Message}");
return false;
}
}
@@ -1120,7 +1117,7 @@ public class TradingBotBase : ITradingBot
}
await LogInformation(
$"🔧 **Closing Trade**\nTicker: `{Config.Ticker}`\nPrice: `${lastPrice}`\n📋 Type: `{tradeToClose.TradeType}`\n📊 Quantity: `{tradeToClose.Quantity}`\n🎯 Closing Position: `{(tradeClosingPosition ? "Yes" : "No")}`");
$"🔧 Closing Trade\nTicker: `{Config.Ticker}`\nPrice: `${lastPrice}`\n📋 Type: `{tradeToClose.TradeType}`\n📊 Quantity: `{tradeToClose.Quantity:F5}`");
decimal quantity = 0;
@@ -1202,7 +1199,7 @@ public class TradingBotBase : ITradingBot
try
{
Logger.LogInformation(
$"🔍 **Fetching Position History from GMX**\nPosition: `{position.Identifier}`\nTicker: `{Config.Ticker}`");
$"🔍 Fetching Position History from GMX\nPosition: `{position.Identifier}`\nTicker: `{Config.Ticker}`");
List<Position> positionHistory = null;
await ServiceScopeHelpers.WithScopedService<IExchangeService>(_scopeFactory,
@@ -1225,7 +1222,7 @@ public class TradingBotBase : ITradingBot
if (gmxPosition != null && gmxPosition.ProfitAndLoss != null)
{
Logger.LogInformation(
$"✅ **GMX Position History Found**\n" +
$"✅ GMX Position History Found\n" +
$"Position: `{position.Identifier}`\n" +
$"GMX Realized PnL (after fees): `${gmxPosition.ProfitAndLoss.Realized:F2}`\n" +
$"Bot's UI Fees: `${position.UiFees:F2}`\n" +
@@ -1289,7 +1286,7 @@ public class TradingBotBase : ITradingBot
}
Logger.LogInformation(
$"📊 **Position Reconciliation Complete**\n" +
$"📊 Position Reconciliation Complete\n" +
$"Position: `{position.Identifier}`\n" +
$"Closing Price: `${closingPrice:F2}`\n" +
$"Used: `{(isProfitable ? "Take Profit" : "Stop Loss")}`\n" +
@@ -1302,7 +1299,7 @@ public class TradingBotBase : ITradingBot
}
Logger.LogWarning(
$"⚠️ **No GMX Position History Found**\nPosition: `{position.Identifier}`\nFalling back to candle-based calculation");
$"⚠️ No GMX Position History Found\nPosition: `{position.Identifier}`\nFalling back to candle-based calculation");
}
catch (Exception ex)
{
@@ -1406,7 +1403,7 @@ public class TradingBotBase : ITradingBot
}
Logger.LogInformation(
$"🛑 **Stop Loss Execution Confirmed**\n" +
$"🛑 Stop Loss Execution Confirmed\n" +
$"Position: `{position.Identifier}`\n" +
$"SL Price: `${closingPrice:F2}` was hit (was `${position.StopLoss.Price:F2}`)\n" +
$"Recent Low: `${minPriceRecent:F2}` | Recent High: `${maxPriceRecent:F2}`");
@@ -1429,7 +1426,7 @@ public class TradingBotBase : ITradingBot
}
Logger.LogInformation(
$"🎯 **Take Profit Execution Confirmed**\n" +
$"🎯 Take Profit Execution Confirmed\n" +
$"Position: `{position.Identifier}`\n" +
$"TP Price: `${closingPrice:F2}` was hit (was `${position.TakeProfit1.Price:F2}`)\n" +
$"Recent Low: `${minPriceRecent:F2}` | Recent High: `${maxPriceRecent:F2}`");
@@ -1480,7 +1477,7 @@ public class TradingBotBase : ITradingBot
}
Logger.LogInformation(
$"✋ **Manual/Exchange Close Detected**\n" +
$"✋ Manual/Exchange Close Detected\n" +
$"Position: `{position.Identifier}`\n" +
$"SL: `${position.StopLoss.Price:F2}` | TP: `${position.TakeProfit1.Price:F2}`\n" +
$"Recent Low: `${minPriceRecent:F2}` | Recent High: `${maxPriceRecent:F2}`\n" +
@@ -1549,21 +1546,21 @@ public class TradingBotBase : ITradingBot
if (position.Open?.Status == TradeStatus.Filled)
{
Logger.LogInformation(
$"✅ **Position Closed Successfully**\nPosition: `{position.SignalIdentifier}`\nPnL: `${position.ProfitAndLoss?.Realized:F2}`");
$"✅ Position Closed Successfully\nPosition: `{position.SignalIdentifier}`\nPnL: `${position.ProfitAndLoss?.Realized:F2}`");
if (position.ProfitAndLoss != null)
{
Config.BotTradingBalance += position.ProfitAndLoss.Realized;
Logger.LogInformation(
string.Format("💰 **Balance Updated**\nNew bot trading balance: `${0:F2}`",
string.Format("💰 Balance Updated\nNew bot trading balance: `${0:F2}`",
Config.BotTradingBalance));
}
}
else
{
Logger.LogInformation(
$"✅ **Position Cleanup**\nPosition: `{position.SignalIdentifier}` was never filled - no balance or PnL changes");
$"✅ Position Cleanup\nPosition: `{position.SignalIdentifier}` was never filled - no balance or PnL changes");
}
}
else
@@ -1574,10 +1571,9 @@ public class TradingBotBase : ITradingBot
if (!Config.IsForBacktest)
{
await ServiceScopeHelpers.WithScopedService<IMessengerService>(_scopeFactory,
messengerService =>
async messengerService =>
{
messengerService.SendClosingPosition(position);
return Task.CompletedTask;
await messengerService.SendClosedPosition(position, Account.User);
});
}
@@ -1646,7 +1642,7 @@ public class TradingBotBase : ITradingBot
{
Positions.Values.First(p => p.SignalIdentifier == signalIdentifier).Status = positionStatus;
await LogInformation(
$"📊 **Position Status Change**\nPosition: `{signalIdentifier}`\nStatus: `{position.Status}` → `{positionStatus}`");
$"📊 Position Status Change\nPosition: `{position.Ticker}`\nDirection: `{position.OriginDirection}`\nNew Status: `{positionStatus}`");
// Update Open trade status when position becomes Filled
if (positionStatus == PositionStatus.Filled && position.Open != null)
@@ -1735,7 +1731,7 @@ public class TradingBotBase : ITradingBot
{
Config.IsForWatchingOnly = !Config.IsForWatchingOnly;
await LogInformation(
$"🔄 **Watch Mode Toggle**\nBot: `{Config.Name}`\nWatch Only: `{(Config.IsForWatchingOnly ? "ON" : "OFF")}`");
$"🔄 Watch Mode Toggle\nBot: `{Config.Name}`\nWatch Only: `{(Config.IsForWatchingOnly ? "ON" : "OFF")}`");
}
/// <summary>
@@ -1743,7 +1739,7 @@ public class TradingBotBase : ITradingBot
/// </summary>
public async Task StopBot()
{
await LogInformation($"🛑 **Bot Stopped**\nBot: `{Config.Name}`\nTicker: `{Config.Ticker}`");
await LogInformation($"🛑 Bot Stopped\nBot: `{Config.Name}`\nTicker: `{Config.Ticker}`");
}
public async Task LogInformation(string message)
@@ -1783,7 +1779,7 @@ public class TradingBotBase : ITradingBot
if (!Config.IsForBacktest)
{
var user = Account.User;
var messageWithBotName = $"🤖 **{user.AgentName} - {Config.Name}**\n{message}";
var messageWithBotName = $"🤖 {user.AgentName} - {Config.Name}\n{message}";
await ServiceScopeHelpers.WithScopedService<IMessengerService>(_scopeFactory,
async messengerService =>
{
@@ -1831,7 +1827,7 @@ public class TradingBotBase : ITradingBot
Positions[position.Identifier] = position;
Logger.LogInformation(
$"👤 **Manual Position Opened**\nPosition: `{position.Identifier}`\nSignal: `{signal.Identifier}`\nAdded to positions list");
$"👤 Manual Position Opened\nPosition: `{position.Identifier}`\nSignal: `{signal.Identifier}`\nAdded to positions list");
return position;
}
@@ -1846,8 +1842,8 @@ public class TradingBotBase : ITradingBot
}
var indicatorNames = Config.Scenario.Indicators.Select(i => i.Type.ToString()).ToList();
var signalText = $"🎯 **New Trading Signal**\n\n" +
$"📊 **Signal Details:**\n" +
var signalText = $"🎯 New Trading Signal\n\n" +
$"📊 Signal Details:\n" +
$"📈 Action: `{signal.Direction}` {Config.Ticker}\n" +
$"⏰ Timeframe: `{Config.Timeframe}`\n" +
$"🎯 Confidence: `{signal.Confidence}`\n" +
@@ -2144,13 +2140,13 @@ public class TradingBotBase : ITradingBot
// Only log if there are actual changes
if (changes.Any())
{
var changeMessage = "⚙️ **Configuration Updated**\n" + string.Join("\n", changes);
var changeMessage = "⚙️ Configuration Updated\n" + string.Join("\n", changes);
await LogInformation(changeMessage);
}
else
{
await LogInformation(
"⚙️ **Configuration Update**\n✅ No changes detected - configuration already up to date");
"⚙️ Configuration Update\n✅ No changes detected - configuration already up to date");
}
return true;
@@ -2227,7 +2223,7 @@ public class TradingBotBase : ITradingBot
var remainingTime = cooldownEndTime - LastCandle.Date;
Logger.LogWarning(
$"⏳ **Cooldown Period Active**\n" +
$"⏳ Cooldown Period Active\n" +
$"Cannot open new positions\n" +
$"Last position closed: `{LastPositionClosingTime:HH:mm:ss}`\n" +
$"Cooldown period: `{Config.CooldownPeriod}` candles\n" +