No Logging cBot
No Logging cBot
04 Jan 2025, 11:22
Hi,
For backtesting Im trying to establish a connection between cbot and my websocket.
I opened TCP 8765 in Windows Defender and my websocket is ready and running:
2025-01-04 11:44:07,752 - INFO - Model loaded successfully
2025-01-04 11:44:09,796 - INFO - Available network interfaces:
2025-01-04 11:44:09,820 - INFO - {2EECBE06-8354-4562-AD30-E34C986B34E5}: 192.168.0.39
2025-01-04 11:44:09,825 - INFO - {BF84D650-AE7C-11EE-A230-806E6F6E6963}: 127.0.0.1
2025-01-04 11:44:09,836 - INFO - server listening on 0.0.0.0:8765
2025-01-04 11:44:09,836 - INFO - Trading server started on ws://0.0.0.0:8765
2025-01-04 11:44:09,836 - INFO - Listening on all network interfaces
2025-01-04 11:44:09,836 - INFO - Server process ID: 9820
2025-01-04 11:44:09,836 - INFO - Server listening status: True
2025-01-04 11:44:09,836 - INFO - Socket family: 2
2025-01-04 11:44:09,836 - INFO - Socket type: 1
2025-01-04 11:44:09,836 - INFO - Socket protocol: 6
2025-01-04 11:44:09,836 - INFO - Socket fileno: 3444
The cbot logs show only this output:
19/10/2017 00:00:00.000 | Info | CBot instance [DRL_Websocket, NZDUSD, m5] started.
19.10.2017 00:00:00.083 | Info | Connection error: Unable to connect to the remote server
29/12/2024 23:59:59.325 | Info | CBot instance [DRL_Websocket, NZDUSD, m5] stopped.
although I ask for more logging output in my cbot code:
using System;
using System.Threading.Tasks;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Text.Json;
using cAlgo.API;
using cAlgo.API.Indicators;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
namespace DRL_Websocket
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class DRLTradingBot : Robot
{
private static readonly HttpClient httpClient = new();
private ClientWebSocket webSocket;
private volatile bool isConnected;
private volatile bool isRunning;
private readonly SemaphoreSlim connectionLock = new(1, 1);
private readonly string[] serverUrls =
{
"ws://127.0.0.1:8765",
"ws://localhost:8765",
"ws://0.0.0.0:8765",
"ws://[::1]:8765",
"ws://host.docker.internal:8765"
};
private DateTime lastTradeTime;
private const double TradeIntervalMinutes = 5;
private const int MaxReconnectAttempts = 5;
private const int ReconnectDelayMs = 5000;
private readonly Queue<string> logQueue = new(MaxLogEntries);
private const int MaxLogEntries = 100;
[Parameter("Stop Loss (pips)", DefaultValue = 50)]
public double StopLossPips { get; set; }
[Parameter("Take Profit (pips)", DefaultValue = 100)]
public double TakeProfitPips { get; set; }
[Parameter("Risk Percentage", DefaultValue = 1.0)]
public double RiskPercentage { get; set; }
[Parameter("Max Spread (pips)", DefaultValue = 3.0)]
public double MaxSpreadPips { get; set; }
protected override async void OnStart()
{
try
{
Print("=== Bot Starting ==="); // Direct print for immediate feedback
LogInfo($"Bot initializing with parameters:");
LogInfo($"Stop Loss: {StopLossPips} pips");
LogInfo($"Take Profit: {TakeProfitPips} pips");
LogInfo($"Risk Percentage: {RiskPercentage}%");
LogInfo($"Max Spread: {MaxSpreadPips} pips");
LogInfo($"Symbol: {SymbolName}");
LogInfo($"Time Frame: {TimeFrame}");
LogInfo($"Account Balance: {Account.Balance}");
LogInfo($"Server Time: {Server.Time}");
await LogNetworkStatus();
LogInfo("Starting main bot processes...");
isRunning = true;
LogInfo("Initializing WebSocket connection...");
await InitializeConnection();
LogInfo("Starting market data processing...");
_ = StartMarketDataProcessing();
LogInfo("Bot startup complete.");
}
catch (Exception ex)
{
LogError($"Critical error during startup: {ex.Message}");
LogError($"Stack trace: {ex.StackTrace}");
if (ex.InnerException != null)
{
LogError($"Inner exception: {ex.InnerException.Message}");
}
}
}
private async Task LogNetworkStatus()
{
try
{
var response = await httpClient.GetAsync("http://www.google.com");
if (response.IsSuccessStatusCode)
{
LogInfo("Internet connectivity: Available");
}
else
{
LogError($"Internet connectivity: Not available (Status: {response.StatusCode})");
}
}
catch (Exception ex)
{
LogError($"Error checking network status: {ex.Message}");
}
}
private async Task InitializeConnection()
{
for (int attempt = 1; attempt <= MaxReconnectAttempts; attempt++)
{
try
{
await ConnectToServer();
if (isConnected)
return;
}
catch (Exception ex)
{
LogError($"Connection attempt {attempt} failed: {ex.Message}");
if (attempt < MaxReconnectAttempts)
await Task.Delay(ReconnectDelayMs);
}
}
LogError("Failed to establish initial connection after maximum attempts");
}
private async Task ConnectToServer()
{
await connectionLock.WaitAsync();
try
{
if (webSocket?.State == WebSocketState.Open)
{
isConnected = true;
LogInfo($"Already connected. WebSocket state: {webSocket.State}");
return;
}
webSocket?.Dispose();
webSocket = new ClientWebSocket();
webSocket.Options.KeepAliveInterval = TimeSpan.FromSeconds(30);
webSocket.Options.SetBuffer(8192, 8192);
// Log system network information
LogInfo($"System Network Info:");
LogInfo($"Machine Name: {Environment.MachineName}");
LogInfo($"OS Version: {Environment.OSVersion}");
bool connected = false;
Exception lastException = null;
foreach (string url in serverUrls)
{
try
{
using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(10));
LogInfo($"Attempting connection to {url}");
LogInfo($"WebSocket State: {webSocket.State}");
var uri = new Uri(url);
LogInfo($"URI Details - Scheme: {uri.Scheme}, Host: {uri.Host}, Port: {uri.Port}");
try
{
await webSocket.ConnectAsync(uri, cancellation.Token);
LogInfo($"Connection attempt completed to {url}");
LogInfo($"Post-connection WebSocket State: {webSocket.State}");
connected = true;
break;
}
catch (WebSocketException wsEx)
{
LogError($"WebSocket error for {url}: {wsEx.WebSocketErrorCode} - {wsEx.Message}");
if (wsEx.InnerException != null)
{
LogError($"Inner WebSocket Exception: {wsEx.InnerException.GetType().Name} - {wsEx.InnerException.Message}");
}
}
catch (Exception ex)
{
LogError($"Connection error for {url}: {ex.Message}");
if (ex.InnerException != null)
{
LogError($"Inner Exception: {ex.InnerException.GetType().Name} - {ex.InnerException.Message}");
}
}
}
catch (Exception ex)
{
lastException = ex;
LogError($"General connection error for {url}: {ex.GetType().Name} - {ex.Message}");
if (ex.InnerException != null)
{
LogError($"Inner Exception: {ex.InnerException.GetType().Name} - {ex.InnerException.Message}");
}
webSocket.Dispose();
webSocket = new ClientWebSocket
{
Options =
{
KeepAliveInterval = TimeSpan.FromSeconds(30)
}
};
webSocket.Options.SetBuffer(8192, 8192);
}
}
if (!connected && lastException != null)
{
LogError($"All connection attempts failed. Last error: {lastException.Message}");
throw lastException;
}
isConnected = connected;
if (connected)
{
LogInfo("Successfully established WebSocket connection");
LogInfo($"Final WebSocket State: {webSocket.State}");
}
}
finally
{
connectionLock.Release();
}
}
private class MarketDataMessage
{
public string Timestamp { get; set; }
public string Symbol { get; set; }
public double Open { get; set; }
public double High { get; set; }
public double Low { get; set; }
public double Close { get; set; }
public double Volume { get; set; }
public double Spread { get; set; }
}
private class TradingActionMessage
{
public int Action { get; set; }
public string Timestamp { get; set; }
public string Symbol { get; set; }
}
private async Task StartMarketDataProcessing()
{
while (isRunning)
{
try
{
if (!isConnected)
{
await InitializeConnection();
if (!isConnected)
{
await Task.Delay(ReconnectDelayMs);
continue;
}
}
await ProcessMarketData();
}
catch (Exception ex)
{
LogError($"Error in market data processing: {ex.Message}");
isConnected = false;
await Task.Delay(ReconnectDelayMs);
}
}
}
private async Task ProcessMarketData()
{
try
{
double currentSpread = Symbol.Spread / Symbol.PipSize;
if (currentSpread > MaxSpreadPips)
{
LogInfo($"Spread too high ({currentSpread:F1} pips). Skipping.");
return;
}
var marketData = new MarketDataMessage
{
Timestamp = Server.Time.ToString("dd/MM/yyyy HH:mm:ss"),
Symbol = SymbolName,
Open = Bars.OpenPrices.Last(0),
High = Bars.HighPrices.Last(0),
Low = Bars.LowPrices.Last(0),
Close = Bars.ClosePrices.Last(0),
Volume = Bars.TickVolumes.Last(0),
Spread = currentSpread
};
var jsonOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
string jsonData = JsonSerializer.Serialize(marketData, jsonOptions);
byte[] buffer = Encoding.UTF8.GetBytes(jsonData);
using var sendCts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
await webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, sendCts.Token);
buffer = new byte[1024];
using var receiveCts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), receiveCts.Token);
if (result.MessageType == WebSocketMessageType.Close)
{
LogInfo("Received close message from server");
isConnected = false;
return;
}
string response = Encoding.UTF8.GetString(buffer, 0, result.Count);
var tradingAction = JsonSerializer.Deserialize<TradingActionMessage>(response, jsonOptions);
if ((Server.Time - lastTradeTime).TotalMinutes >= TradeIntervalMinutes)
{
await ExecuteTradeAction(tradingAction.Action);
lastTradeTime = Server.Time;
}
await Task.Delay(1000);
}
catch (WebSocketException ex)
{
LogError($"WebSocket error: {ex.Message}");
isConnected = false;
throw;
}
catch (Exception ex)
{
LogError($"Error processing market data: {ex.Message}");
throw;
}
}
private async Task ExecuteTradeAction(int action)
{
try
{
switch (action)
{
case 1:
await OpenTradeWithManagement(TradeType.Buy);
break;
case 2:
await OpenTradeWithManagement(TradeType.Sell);
break;
default:
LogInfo("Holding current position");
break;
}
}
catch (Exception ex)
{
LogError($"Trade execution error: {ex.Message}");
}
}
private async Task OpenTradeWithManagement(TradeType tradeType)
{
await CloseAllPositions();
double volume = CalculateVolume();
var positionName = $"DRL_{tradeType}_{DateTime.UtcNow:ddMMyyyyHHmmss}";
var stopLoss = tradeType == TradeType.Buy
? Symbol.Bid - (StopLossPips * Symbol.PipSize)
: Symbol.Ask + (StopLossPips * Symbol.PipSize);
var takeProfit = tradeType == TradeType.Buy
? Symbol.Bid + (TakeProfitPips * Symbol.PipSize)
: Symbol.Ask - (TakeProfitPips * Symbol.PipSize);
try
{
ExecuteMarketOrder(tradeType, SymbolName, volume, positionName, stopLoss, takeProfit);
LogInfo($"Executed {tradeType} order: Volume={volume}, SL={stopLoss}, TP={takeProfit}");
}
catch (Exception ex)
{
LogError($"Failed to execute {tradeType} order: {ex.Message}");
}
}
private async Task CloseAllPositions()
{
foreach (var position in Positions)
{
try
{
position.Close();
LogInfo($"Closed position {position.Label}");
await Task.Delay(100);
}
catch (Exception ex)
{
LogError($"Error closing position {position.Label}: {ex.Message}");
}
}
}
private double CalculateVolume()
{
double riskAmount = Account.Balance * (RiskPercentage / 100.0);
double pipValue = Symbol.PipValue;
double volume = (riskAmount / (StopLossPips * pipValue));
volume = Math.Round(volume, 2);
volume = Math.Max(Symbol.VolumeInUnitsMin, Math.Min(Symbol.VolumeInUnitsMax, volume));
return volume;
}
private void LogInfo(string message)
{
try
{
string logMessage = $"{Server.Time:dd/MM/yyyy HH:mm:ss.fff} | Info | {message}";
Print(logMessage); // cAlgo's Print method
System.Diagnostics.Debug.WriteLine(logMessage); // Additional debug output
AddToLogQueue(logMessage);
// Force log to file for debugging
string logPath = $"DRL_Bot_{DateTime.Now:yyyyMMdd}.log";
System.IO.File.AppendAllText(logPath, logMessage + Environment.NewLine);
}
catch (Exception ex)
{
Print($"Logging error: {ex.Message}");
}
}
private void LogError(string message)
{
try
{
string logMessage = $"{Server.Time:dd/MM/yyyy HH:mm:ss.fff} | ERROR | {message}";
Print(logMessage); // cAlgo's Print method
System.Diagnostics.Debug.WriteLine(logMessage); // Additional debug output
AddToLogQueue(logMessage);
// Force log to file for debugging
string logPath = $"DRL_Bot_Error_{DateTime.Now:yyyyMMdd}.log";
System.IO.File.AppendAllText(logPath, logMessage + Environment.NewLine);
}
catch (Exception ex)
{
Print($"Logging error: {ex.Message}");
}
}
private void AddToLogQueue(string message)
{
lock (logQueue)
{
logQueue.Enqueue(message);
while (logQueue.Count > MaxLogEntries)
logQueue.Dequeue();
}
}
protected override void OnStop()
{
LogInfo("Bot stopping...");
isRunning = false;
isConnected = false;
webSocket?.Dispose();
}
}
}
Why is there no more logging output?
Thank you