Source code for bbstrader.api

"""
Overview
========

The API Module provides a high-level client for interacting with the MetaTrader 5 platform.
It serves as the primary interface for connecting to, retrieving data from, and sending commands
to a MetaTrader 5 terminal from a Python application. The module is designed to simplify
interactions and provide convenient data handling.

Features
========

- **High-Level MT5 Client**: A simplified client (`Mt5client`) for easy access to MetaTrader 5 functionalities.
- **Dynamic Object Representation**: Automatically patches MetaTrader 5 data objects for better string representation, making debugging easier.
- **DataFrame Conversion**: Includes a utility function (`trade_object_to_df`) to quickly convert lists of MT5 trade objects (like deals, orders, positions) into pandas DataFrames for analysis.
- **Handler-Based Architecture**: Uses a handler class (`Mt5Handlers`) to manage the underlying MetaTrader 5 API calls, promoting modularity.

Components
==========

- **Mt5client**: The main client instance used to interact with the MetaTrader 5 terminal.
- **Mt5Handlers**: A class that encapsulates the direct calls to the MetaTrader 5 API.
- **Helper Functions**:
  - `trade_object_to_df`: Converts lists of trade-related objects to pandas DataFrames.
  - Dynamic patching of `__str__` and `__repr__` for improved object inspection.

Notes
=====

This module requires a running MetaTrader 5 terminal and the `MetaTrader5` Python package to be installed.
The connection is managed by the `Mt5client`.
"""

from operator import attrgetter

import pandas as pd

from bbstrader.api.handlers import Mt5Handlers
from bbstrader.api.metatrader_client import *  # type: ignore # noqa: F403

# ruff: noqa: F405
classes_to_patch = [
    AccountInfo,
    BookInfo,
    OrderCheckResult,
    OrderSentResult,
    RateInfo,
    SymbolInfo,
    TerminalInfo,
    TickInfo,
    TradeDeal,
    TradeOrder,
    TradePosition,
    TradeRequest,
]


[docs] def dynamic_str(self): fields = set() for name in dir(self): if name.startswith("_"): continue try: value = getattr(self, name) if not callable(value): fields.add(f"{name}={value!r}") except Exception: pass return f"{type(self).__name__}({', '.join(fields)})"
for cls in classes_to_patch: cls.__str__ = dynamic_str cls.__repr__ = dynamic_str
[docs] def trade_object_to_df(obj_list): """ Fast conversion of a list of C++ bound objects to a pandas DataFrame. """ if not obj_list: return pd.DataFrame() first_obj = obj_list[0] columns = [ name for name in dir(first_obj) if not name.startswith("_") and not callable(getattr(first_obj, name)) ] fetcher = attrgetter(*columns) data = [fetcher(obj) for obj in obj_list] df = pd.DataFrame(data, columns=columns) return df
Mt5client = MetaTraderClient(Mt5Handlers)