Skip to content

✅ MT5Service - Account Methods (Mid-Level API)

Important: Read This First

MT5Service is an architectural layer between high-level (Sugar) and low-level (Account) APIs.

Understanding the 4 Methods:

Method Direct Use Value Architectural Role
get_account_summary() HIGH - Aggregates 14 props + datetime conversion Used by Sugar
get_account_double() NONE - Just calls account.account_info_double() Used by Sugar
get_account_integer() NONE - Just calls account.account_info_integer() Used by Sugar
get_account_string() NONE - Just calls account.account_info_string() Used by Sugar

What This Means:

🏗️ Architecture (3 layers):

MT5Sugar (HIGH)     service.get_account_double()  Sugar uses Service methods
MT5Service (MID)    account.account_info_double()  Service is a pass-through layer
MT5Account (LOW)    gRPC call to MT5 server

For direct MT5Service usage:

  • Use get_account_summary() - real improvement (1 call vs 14 calls)
  • Skip other 3 methods - no value, just call MT5Account directly

For MT5Sugar users:

  • All methods work perfectly - the layer serves its architectural purpose

API Layer: MID-LEVEL - wrappers over MT5Account with Python native types

Implementation:

These methods are implemented in src/pymt5/mt5_service.py, which wraps package/MetaRpcMT5/helpers/mt5_account.py low-level API.

Example files:

  • examples/2_service/04_service_demo.py - comprehensive demo of all MT5Service methods including account information (STEP 2)

Why These Methods Exist

Real Value: get_account_summary()

The main benefit of MT5Service for account information is get_account_summary():

What it does: - Makes 5 internal RPC calls (1 summary + 4 individual properties) - Converts protobuf Timestamp Python datetime - Aggregates 14 fields into one clean AccountSummary dataclass - Single method call instead of 14 separate account_info_*() calls

Example:

# MT5Service - ONE call gets everything
summary = await service.get_account_summary()
print(f"Balance: {summary.balance}, Equity: {summary.equity}")
print(f"Leverage: {summary.leverage}, Server time: {summary.server_time}")  # datetime!

# vs MT5Account - 14 separate calls needed
balance = await account.account_info_double(account_info_pb2.ACCOUNT_BALANCE)
equity = await account.account_info_double(account_info_pb2.ACCOUNT_EQUITY)
leverage = await account.account_info_integer(account_info_pb2.ACCOUNT_LEVERAGE)
# ... 11 more calls ...

Other Methods: Architectural Layer

get_account_double(), get_account_integer(), get_account_string() are thin wrappers that serve as architectural layer:

Why they exist: - MT5Sugar (high-level) uses them - maintains layered architecture (Sugar Service Account) - Unified interface - all methods accessible through one class - Consistent naming - get_* prefix across all Service methods - No processing - direct pass-through to account.account_info_*()

For end users: If you're using MT5Service directly (not Sugar), calling MT5Account is identical. These wrappers add no value.

For MT5Sugar: These are essential - Sugar must work through Service, not directly with Account (layered architecture).


All 4 Methods

Method Returns Implementation
get_account_summary() AccountSummary dataclass Aggregates 5 RPC calls + converts Timestamp datetime
get_account_double(property_id) float return await self._account.account_info_double(property_id)
get_account_integer(property_id) int return await self._account.account_info_integer(property_id)
get_account_string(property_id) str return await self._account.account_info_string(property_id)

➕ AccountSummary Dataclass (DTO)

@dataclass
class AccountSummary:
    """Complete account information in one convenient structure."""

    login: int                                      # Account login number
    balance: float                                  # Account balance in deposit currency
    equity: float                                   # Account equity (Balance + Floating P&L)
    user_name: str                                  # Client name
    leverage: int                                   # Account leverage (e.g., 100 for 1:100)
    trade_mode: Any                                 # Account trade mode (demo/real/contest)
    company_name: str                               # Broker company name
    currency: str                                   # Deposit currency (USD, EUR, etc.)
    server_time: Optional[datetime]                 # Server time (already datetime!)
    utc_timezone_shift_minutes: int                 # UTC timezone shift in minutes
    credit: float                                   # Credit facility amount
    margin: float                                   # Margin used for open positions
    free_margin: float                              # Free margin available for trading
    margin_level: float                             # Margin level percentage (equity/margin * 100)
    profit: float                                   # Current floating profit/loss

Advantage: All 14 important properties in one dataclass, server_time is already datetime (no need for manual conversion).


Method Signatures

1) get_account_summary

async def get_account_summary(
    self,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> AccountSummary

Returns all account information in a single call (14 fields in one dataclass).

Technical: Makes 5 internal RPC calls: 1. account_summary() - gets 11 basic fields 2-5. account_info_double() x 4 - gets margin, free_margin, margin_level, profit

Result: AccountSummary dataclass with 14 fields in native Python types.

Advantage: Single method call vs 14 separate AccountInfo* calls (93% code reduction).


2) get_account_double

async def get_account_double(
    self,
    property_id: account_info_pb2.AccountInfoDoublePropertyType,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> float

Available property_id:

from MetaRpcMT5 import mt5_term_api_account_information_pb2 as account_info_pb2

# Available properties:
ACCOUNT_BALANCE = 0          # Account balance
ACCOUNT_CREDIT = 1           # Credit
ACCOUNT_PROFIT = 2           # Current profit/loss
ACCOUNT_EQUITY = 3           # Equity (balance + floating P&L)
ACCOUNT_MARGIN = 4           # Used margin
ACCOUNT_MARGIN_FREE = 5      # Free margin
ACCOUNT_MARGIN_LEVEL = 6     # Margin level (%)
ACCOUNT_MARGIN_SO_CALL = 7   # Margin call level
ACCOUNT_MARGIN_SO_SO = 8     # Stop out level
ACCOUNT_MARGIN_INITIAL = 9   # Initial margin
ACCOUNT_MARGIN_MAINTENANCE = 10  # Maintenance margin
ACCOUNT_ASSETS = 11          # Current assets
ACCOUNT_LIABILITIES = 12     # Current liabilities
ACCOUNT_COMMISSION_BLOCKED = 13  # Blocked commission

Returns: float value directly.

Technical: Thin wrapper over account.account_info_double() which already returns float. Provides consistent get_* naming convention.


3) get_account_integer

async def get_account_integer(
    self,
    property_id: account_info_pb2.AccountInfoIntegerPropertyType,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> int

Available property_id:

ACCOUNT_LOGIN = 0            # Account number
ACCOUNT_TRADE_MODE = 1       # Trade mode (0=demo, 2=real)
ACCOUNT_LEVERAGE = 2         # Leverage (e.g., 100 for 1:100)
ACCOUNT_LIMIT_ORDERS = 3     # Max pending orders
ACCOUNT_MARGIN_SO_MODE = 4   # Margin SO mode
ACCOUNT_TRADE_ALLOWED = 5    # Trading allowed (0/1)
ACCOUNT_TRADE_EXPERT = 6     # EA trading allowed (0/1)
ACCOUNT_MARGIN_MODE = 7      # Margin calculation mode
ACCOUNT_CURRENCY_DIGITS = 8  # Currency decimal places
ACCOUNT_FIFO_CLOSE = 9       # FIFO close mandatory (0/1)
ACCOUNT_HEDGE_ALLOWED = 10   # Hedging allowed (0/1)

Returns: int value directly.

Technical: Thin wrapper over account.account_info_integer() which already returns int. Provides consistent get_* naming convention.


4) get_account_string

async def get_account_string(
    self,
    property_id: account_info_pb2.AccountInfoStringPropertyType,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> str

Available property_id:

ACCOUNT_NAME = 0             # Account owner name
ACCOUNT_SERVER = 1           # Trading server name
ACCOUNT_CURRENCY = 2         # Deposit currency (USD, EUR, etc.)
ACCOUNT_COMPANY = 3          # Broker company name

Returns: str value directly.

Technical: Thin wrapper over account.account_info_string() which already returns str. Provides consistent get_* naming convention.


🔗 Usage Examples

async def display_account_info(service: MT5Service):
    # BEST way - use get_account_summary for multiple properties
    summary = await service.get_account_summary()

    print(f"Account: {summary.login}")
    print(f"Balance: ${summary.balance:.2f} {summary.currency}")
    print(f"Equity: ${summary.equity:.2f}")
    print(f"Floating P/L: ${summary.profit:.2f}")
    print(f"Margin: ${summary.margin:.2f}")
    print(f"Free Margin: ${summary.free_margin:.2f}")
    print(f"Margin Level: {summary.margin_level:.2f}%")
    print(f"Leverage: 1:{summary.leverage}")
    print(f"Broker: {summary.company_name}")

    # server_time is already datetime (no conversion needed!)
    if summary.server_time:
        print(f"Server time: {summary.server_time.strftime('%Y-%m-%d %H:%M:%S')}")

Building a Dashboard

async def display_dashboard(service: MT5Service):
    """Display comprehensive account dashboard."""

    summary = await service.get_account_summary()

    print("=" * 60)
    print(f"{'ACCOUNT DASHBOARD':^60}")
    print("=" * 60)

    # Account Info
    print(f"\nAccount Information:")
    print(f"   Login:          {summary.login}")
    print(f"   Name:           {summary.user_name}")
    print(f"   Broker:         {summary.company_name}")
    print(f"   Currency:       {summary.currency}")
    print(f"   Leverage:       1:{summary.leverage}")

    # Financial Status
    print(f"\nFinancial Status:")
    print(f"   Balance:        ${summary.balance:,.2f}")
    print(f"   Equity:         ${summary.equity:,.2f}")
    print(f"   Floating P/L:   ${summary.profit:+,.2f}")
    print(f"   Credit:         ${summary.credit:,.2f}")

    # Margin Status
    print(f"\nMargin Status:")
    print(f"   Used Margin:    ${summary.margin:,.2f}")
    print(f"   Free Margin:    ${summary.free_margin:,.2f}")
    print(f"   Margin Level:   {summary.margin_level:.2f}%")

    # Warning if margin level is low
    if summary.margin_level < 100 and summary.margin > 0:
        print(f"\nWARNING: Low margin level!")

    print("=" * 60)

Quick Reference

For multiple account properties: Use get_account_summary()

summary = await service.get_account_summary()  # Gets all 14 fields in one call

For single property (rare use case): Use get_account_double/integer/string() or call MT5Account directly

# Both are identical:
balance = await service.get_account_double(account_info_pb2.ACCOUNT_BALANCE)
balance = await account.account_info_double(account_info_pb2.ACCOUNT_BALANCE)



Summary

Real value for end users: - get_account_summary() - Aggregates 14 properties in one call + converts datetime (93% code reduction)

Architectural layer (for MT5Sugar): - get_account_double/integer/string() - Direct pass-through to MT5Account - Used by MT5Sugar to maintain layered architecture (Sugar Service Account) - For direct MT5Service usage: no value, call MT5Account instead

Recommendation: - Using MT5Sugar? These methods work seamlessly through the architecture - Using MT5Service directly? Only use get_account_summary(). For single properties, call MT5Account.