Utilities·General·Beginner

Logging Setup

Set up structured logging for trading bots — rotating file handlers, log levels, contextual fields, and integration with monitoring.

loggingmonitoringdebugging

Bitpredict Logging Framework and Strategy Outline

Introduction to Logging

This section outlines the logging framework employed within the Bitpredict application. Effective logging is crucial for monitoring system behavior, debugging issues, and maintaining an audit trail of operations.

Purpose of Logging

Logging functionality captures runtime activities, errors, strategy signals, and exchange operations. This capability is essential for:

  • Debugging: Facilitates identification and resolution of software defects.
  • Monitoring: Provides real-time insights into system performance and health.
  • Audit History: Establishes a verifiable record of system events.
  • Failure Analysis: Assists in post-mortem examination of system failures.

Logging Framework Components

The Python logging module is composed of several key elements:

ComponentPurpose
LoggerServes as the entry point for log messages.
HandlerDispatches log records to specific destinations.
FormatterDefines the layout of log records.
LevelSpecifies the minimum severity of messages to be processed.

Standard Log Levels

The logging module defines several standard severity levels:

LevelPurpose
DEBUGDetailed information, typically of interest only when diagnosing problems.
INFOConfirmation that things are working as expected.
WARNINGAn indication that something unexpected happened, or indicative of some problem in the near future (e.g., ‘disk space low’). The software is still working as expected.
ERRORDue to a more serious problem, the software has not been able to perform some function.
CRITICALA serious error, indicating that the program itself may be unable to continue running.

Dependency Installation

[9]
# Install pandas library, primarily for log inspection or data processing tasks.
!pip install pandas
Requirement already satisfied: pandas in /usr/local/lib/python3.12/dist-packages (2.2.2)
Requirement already satisfied: numpy>=1.26.0 in /usr/local/lib/python3.12/dist-packages (from pandas) (2.0.2)
Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.12/dist-packages (from pandas) (2.9.0.post0)
Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.12/dist-packages (from pandas) (2025.2)
Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.12/dist-packages (from pandas) (2026.1)
Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.12/dist-packages (from python-dateutil>=2.8.2->pandas) (1.17.0)

Library Imports

[10]
import logging          # Standard library for logging
import logging.handlers # Handlers for log file rotation
import sys              # System-specific parameters and functions (for stdout)
import json             # For JSON serialization (if applicable for structured logs)

from pathlib import Path      # Object-oriented filesystem paths
from datetime import datetime, timezone # For timestamping log entries

Logging Configuration

Console Logging Setup

Purpose: Configure a logger to output messages directly to the standard output stream (terminal or notebook output).

[11]
def setup_console_logger():
    """
    Configures and returns a logger for console output.

    The logger is named 'bitpredict' and is set to DEBUG level.
    Log messages are directed to sys.stdout and formatted with timestamp, level, and message.
    """
    logger = logging.getLogger("bitpredict")

    # Set the logging level to DEBUG to capture all messages.
    logger.setLevel(logging.DEBUG)

    # Create a console output handler.
    handler = logging.StreamHandler(sys.stdout)

    # Define the log message format.
    formatter = logging.Formatter(
        "%(asctime)s | "
        "%(levelname)s | "
        "%(message)s"
    )

    # Assign the formatter to the handler.
    handler.setFormatter(formatter)

    # Add the handler to the logger.
    logger.addHandler(handler)

    return logger

Console Logging Demonstration

[12]
# Initialize the console logger.
logger = setup_console_logger()

# Demonstrate logging at different severity levels.
logger.info("OHLCV fetch completed")
logger.warning("API response delayed")
logger.error("Order rejected")
2026-05-20 13:06:24,438 | INFO | OHLCV fetch completed
2026-05-20 13:06:24,438 | INFO | OHLCV fetch completed
INFO:bitpredict:OHLCV fetch completed
2026-05-20 13:06:24,441 | WARNING | API response delayed
2026-05-20 13:06:24,441 | WARNING | API response delayed
WARNING:bitpredict:API response delayed
2026-05-20 13:06:24,444 | ERROR | Order rejected
2026-05-20 13:06:24,444 | ERROR | Order rejected
ERROR:bitpredict:Order rejected

File Logging Setup

Purpose: Configure a logger to persist log messages to a disk file, with automatic rotation.

[13]
def setup_file_logger():
    """
    Configures and returns a logger for file output with rotation.

    The logger is named 'bitpredict.file' and is set to INFO level.
    Log messages are written to 'bitpredict.log', with a maximum size of 10 MB
    and 5 backup files. The format includes timestamp, level, and message.
    """
    logger = logging.getLogger("bitpredict.file")

    # Set the logging level to INFO.
    logger.setLevel(logging.INFO)

    # Create a rotating file handler.
    # Logs are written to 'bitpredict.log'.
    # Max file size is 10 MB; up to 5 backup files are kept.
    handler = logging.handlers.RotatingFileHandler(
        "bitpredict.log",
        maxBytes=10 * 1024 * 1024,
        backupCount=5,
    )

    # Define the log message format.
    formatter = logging.Formatter(
        "%(asctime)s | "
        "%(levelname)s | "
        "%(message)s"
    )

    # Assign the formatter to the handler.
    handler.setFormatter(formatter)

    # Add the handler to the logger.
    logger.addHandler(handler)

    return logger

Log File Rotation Mechanism

File logging employs a rotation mechanism to manage disk space. When the primary log file (bitpredict.log) reaches its maximum configured size (e.g., 10 MB), it is renamed (e.g., to bitpredict.log.1), and a new empty bitpredict.log file is created. Older backup files are sequentially renamed (e.g., bitpredict.log.1 becomes bitpredict.log.2), and the oldest backup is deleted once the backupCount limit is exceeded.

Example sequence of log files:

bitpredict.log
bitpredict.log.1
bitpredict.log.2

This ensures that log files do not indefinitely consume disk space.

Module-Specific Loggers

Purpose: Create distinct loggers for different modules or components of an application, enabling fine-grained control over logging behavior and output destinations for specific parts of the codebase.

[14]
def get_module_logger(name):
    """
    Returns a child logger for a specific module or component.

    Child loggers inherit properties from their parent ('bitpredict' in this case)
    but allow for module-specific logging configurations.

    Args:
        name (str): The name of the module or component (e.g., 'data', 'execution').

    Returns:
        logging.Logger: A logger instance for the specified module.
    """
    return logging.getLogger(
        f"bitpredict.{name}"
    )

Module Logger Instantiation Example

[15]
# Instantiate loggers for specific application modules.
# The 'data_logger' will handle messages related to data processing.
data_logger = get_module_logger(
    "data"
)

# The 'execution_logger' will handle messages related to strategy execution.
execution_logger = get_module_logger(
    "execution"
)

Overall Logging Architecture

The general flow of log messages within the application follows a hierarchical structure:

Application Components
         ↓
 Logger Instances (e.g., 'bitpredict', 'bitpredict.data', 'bitpredict.execution')
         ↓
 Handler (e.g., ConsoleHandler, RotatingFileHandler)
         ↓
 Destination (e.g., Console Output, Log File)

This architecture enables flexible routing and formatting of log data to various output destinations.

Strategy Outline: Overview of the Trading System

This section describes the high-level architecture and operational flow of the automated trading strategy. The system is designed to execute trades based on predefined algorithmic rules, integrating market data analysis with robust execution and monitoring capabilities.

Core Components of the Strategy

The trading strategy comprises several interconnected modules, each responsible for a specific aspect of the trading process:

  1. Market Data Ingestion: Acquires real-time and historical market data (e.g., OHLCV, order book data) from exchanges.
  2. Signal Generation: Analyzes ingested data using technical indicators, statistical models, or machine learning algorithms to identify potential trading opportunities.
  3. Risk Management: Implements rules to control exposure, calculate position sizing, and define stop-loss/take-profit levels.
  4. Order Execution: Submits and manages trade orders with target exchanges, including order placement, modification, and cancellation.
  5. Portfolio Management: Tracks current positions, evaluates performance metrics, and adjusts allocation dynamically.
  6. Performance Monitoring: Logs and visualizes key performance indicators (KPIs) to assess strategy effectiveness and identify areas for improvement.

Strategy Execution Flow

The operational sequence of the strategy typically follows these steps:

Initialize System
       ↓
Fetch Market Data
       ↓
Generate Trading Signals
       ↓
Evaluate Risk & Position Sizing
       ↓
Execute Orders (if signal is valid)
       ↓
Monitor Open Positions & Market Conditions
       ↓
Update Portfolio & Log Performance
       ↓
(Loop or Event-Driven Cycle)

Integration with Logging Framework

Each component of the strategy is integrated with the logging framework. Critical events, such as data acquisition failures, signal generation triggers, order execution results, and risk management breaches, are systematically logged. This integration ensures comprehensive visibility into the strategy's operation, facilitating real-time monitoring and post-execution analysis.

[15]