No Logging cBot

Created at 04 Jan 2025, 11:22
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
ZY

zytotoxiziteat

Joined 04.08.2021

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


@zytotoxiziteat