Skip to content

✅ MT5Service - Symbol Methods (Mid-Level API)

Important: Read This First

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

Understanding the 13 Methods:

Method Direct Use Value Architectural Role
get_symbol_params_many() VERY HIGH - Aggregates 17 fields + unpacks protobuf list Used by Sugar
get_symbol_tick() HIGH - Unix timestamp datetime + unpacks 8 fields Used by Sugar
get_symbol_session_quote() HIGH - 2x protobuf Timestamp datetime Used by Sugar
get_symbol_session_trade() HIGH - 2x protobuf Timestamp datetime Used by Sugar
get_symbol_margin_rate() MEDIUM - Unpacks protobuf + creates dataclass Used by Sugar
get_symbols_total() LOW - Unpacks data.total from protobuf Used by Sugar
symbol_exist() LOW - Unpacks (data.exists, data.is_custom) Used by Sugar
get_symbol_name() LOW - Unpacks data.name from protobuf Used by Sugar
symbol_select() LOW - Unpacks data.success from protobuf Used by Sugar
is_symbol_synchronized() LOW - Unpacks data.synchronized from protobuf Used by Sugar
get_symbol_double() LOW - Unpacks data.value from protobuf Used by Sugar
get_symbol_integer() LOW - Unpacks data.value from protobuf Used by Sugar
get_symbol_string() LOW - Unpacks data.value from protobuf Used by Sugar

What This Means:

🏗️ Architecture (3 layers):

MT5Sugar (HIGH)     service.get_symbol_tick()      Sugar uses Service methods
MT5Service (MID)    account.symbol_info_tick()     Service unpacks protobuf + converts datetime
MT5Account (LOW)    gRPC call protobuf Data

Key difference from Account methods:

  • ALL symbol methods have value - MT5Account returns protobuf Data objects that need unpacking
  • Protobuf unpacking - Service extracts values from data.value, data.total, etc.
  • Datetime conversion - 3 methods convert timestamps/protobuf Timestamps to Python datetime
  • Dataclass creation - Cleaner API with typed dataclasses instead of protobuf messages

For direct MT5Service usage:

  • Use all methods - they all add value through protobuf unpacking
  • High-value methods - get_symbol_params_many(), get_symbol_tick(), session methods
  • Low-value methods - simple unpacking, but still saves you from manual data.value extraction

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 with convenient dataclasses and automatic type conversion.

Example files:

  • examples/2_service/04_service_demo.py - comprehensive demo of all MT5Service methods including symbol information

Why These Methods Exist

Real Value: Protobuf Unpacking + Datetime Conversion

Unlike Account methods, Symbol methods in MT5Service all add real value because MT5Account returns protobuf Data objects:

Problem with MT5Account (Low-level):

# MT5Account returns protobuf Data objects - need manual unpacking
data = await account.symbol_info_double(
    symbol="EURUSD",
    property=market_info_pb2.SYMBOL_BID
)
bid = data.value  # Manual extraction from protobuf wrapper

# Tick time is Unix timestamp - need manual conversion
tick_data = await account.symbol_info_tick("EURUSD")
tick_time = datetime.fromtimestamp(tick_data.time)  # Manual datetime conversion

Solution with MT5Service (Mid-level):

# Service unpacks protobuf automatically - returns native types
bid = await service.get_symbol_double(
    symbol="EURUSD",
    property=market_info_pb2.SYMBOL_BID
)  # Already float, not protobuf Data!

# Tick with datetime already converted
tick = await service.get_symbol_tick("EURUSD")
print(tick.time)  # Already datetime object!

What MT5Service provides:

  1. Protobuf unpacking (all 13 methods):

  2. MT5Account: return res.data (protobuf object)

  3. MT5Service: return data.value (native Python type)

  4. Datetime conversion (3 methods):

  5. get_symbol_tick(): Unix timestamp datetime.fromtimestamp()

  6. get_symbol_session_quote(): protobuf Timestamp ToDatetime() x2
  7. get_symbol_session_trade(): protobuf Timestamp ToDatetime() x2

  8. Data aggregation (1 method):

  9. get_symbol_params_many(): 17 fields in one call instead of 17 separate calls

  10. Clean dataclasses:

  11. SymbolTick, SymbolParams, SessionTime, SymbolMarginRate instead of protobuf messages

Architectural purpose:

  • MT5Sugar uses these methods to maintain layered architecture (Sugar Service Account)
  • Direct users also benefit - all methods add value through unpacking and conversion

All 13 Methods

Method Returns Description
get_symbols_total() int Get count of available symbols
symbol_exist() Tuple[bool, bool] Check if symbol exists (exists, is_custom)
get_symbol_name() str Get symbol name by index
symbol_select() bool Add/remove symbol from Market Watch
is_symbol_synchronized() bool Check if symbol data is synchronized
get_symbol_double() float Get double property (Bid, Ask, Point, etc.)
get_symbol_integer() int Get integer property (Digits, Spread, etc.)
get_symbol_string() str Get string property (Description, Currency, etc.)
get_symbol_margin_rate() SymbolMarginRate Get margin rates for order type
get_symbol_tick() SymbolTick Get current tick (time auto-converted to datetime)
get_symbol_session_quote() SessionTime Get quote session times (as datetime)
get_symbol_session_trade() SessionTime Get trading session times (as datetime)
get_symbol_params_many() Tuple[List[SymbolParams], int] Get comprehensive data for multiple symbols

➕ Dataclasses (DTOs)

SymbolTick

@dataclass
class SymbolTick:
    """
    Current tick information for a symbol.

    ADVANTAGE: Time is already converted from Unix timestamp to datetime.
    """
    time: datetime          # Tick time (converted from Unix timestamp)
    bid: float              # Current Bid price
    ask: float              # Current Ask price
    last: float             # Last deal price
    volume: int             # Tick volume
    time_ms: int            # Tick time in milliseconds
    flags: int              # Tick flags
    volume_real: float      # Tick volume with decimal precision

SymbolMarginRate

@dataclass
class SymbolMarginRate:
    """Margin rate information for a symbol."""
    initial_margin_rate: float          # Initial margin rate
    maintenance_margin_rate: float      # Maintenance margin requirement

SessionTime

@dataclass
class SessionTime:
    """Trading session time range."""
    from_time: datetime     # Session start time (already datetime)
    to_time: datetime       # Session end time (already datetime)

SymbolParams

@dataclass
class SymbolParams:
    """
    Comprehensive symbol information.

    ADVANTAGE: All 17 important symbol parameters in one structure.
    Much more convenient than making multiple calls to SymbolInfoDouble/Integer/String.
    """
    name: str                   # Symbol name
    bid: float                  # Current Bid price
    ask: float                  # Current Ask price
    last: float                 # Last deal price
    point: float                # Point size (minimal price change)
    digits: int                 # Number of decimal places
    spread: int                 # Current spread in points
    volume_min: float           # Minimum volume for trading
    volume_max: float           # Maximum volume for trading
    volume_step: float          # Volume step
    trade_tick_size: float      # Trade tick size
    trade_tick_value: float     # Trade tick value
    trade_contract_size: float  # Contract size
    swap_long: float            # Swap for long positions
    swap_short: float           # Swap for short positions
    margin_initial: float       # Initial margin requirement
    margin_maintenance: float   # Maintenance margin requirement

Method Signatures

1) get_symbols_total

async def get_symbols_total(
    self,
    selected_only: bool,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> int

Get count of available symbols.

Args: - selected_only: True to count only Market Watch symbols, False for all

Returns: int count directly (no Data struct)

Technical: Low-level returns SymbolsTotalData with data.total wrapper. This auto-extracts the count.


2) symbol_exist

async def symbol_exist(
    self,
    symbol: str,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> Tuple[bool, bool]

Check if symbol exists in terminal.

Args: - symbol: Symbol name to check

Returns: Tuple[exists, is_custom] - exists: True if symbol exists - is_custom: True if custom symbol


3) get_symbol_name

async def get_symbol_name(
    self,
    index: int,
    selected_only: bool,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> str

Get symbol name by index position.

Args: - index: Symbol index (starting at 0) - selected_only: True to use only Market Watch symbols

Returns: Symbol name string directly

Usage: Iterate through all symbols with range(get_symbols_total()).


4) symbol_select

async def symbol_select(
    self,
    symbol: str,
    select: bool,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> bool

Add/remove symbol from Market Watch.

Args: - symbol: Symbol name - select: True to add, False to remove

Returns: Success status


5) is_symbol_synchronized

async def is_symbol_synchronized(
    self,
    symbol: str,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> bool

Check if symbol data is synchronized with broker server.

Args: - symbol: Symbol name to check

Returns: True if synchronized, False otherwise

Usage: Check before requesting tick data to ensure it's up-to-date.


6) get_symbol_double

async def get_symbol_double(
    self,
    symbol: str,
    property: market_info_pb2.SymbolInfoDoubleProperty,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> float

Get individual symbol double property.

Available properties:

from MetaRpcMT5 import mt5_term_api_market_info_pb2 as market_info_pb2

# Price properties:
SYMBOL_BID                  # Current Bid price
SYMBOL_ASK                  # Current Ask price
SYMBOL_LAST                 # Last deal price

# Size properties:
SYMBOL_POINT                # Point size (0.00001 for EURUSD)
SYMBOL_TRADE_TICK_VALUE     # Tick value in deposit currency
SYMBOL_TRADE_TICK_SIZE      # Tick size in points
SYMBOL_TRADE_CONTRACT_SIZE  # Contract size (100000 for forex)

# Volume properties:
SYMBOL_VOLUME_MIN           # Minimum volume
SYMBOL_VOLUME_MAX           # Maximum volume
SYMBOL_VOLUME_STEP          # Volume step

# Swap properties:
SYMBOL_SWAP_LONG            # Swap for long positions
SYMBOL_SWAP_SHORT           # Swap for short positions

# Margin properties:
SYMBOL_MARGIN_INITIAL       # Initial margin
SYMBOL_MARGIN_MAINTENANCE   # Maintenance margin

Returns: float value directly

Technical: Low-level returns SymbolInfoDoubleResponse with data.value. This extracts the float.


7) get_symbol_integer

async def get_symbol_integer(
    self,
    symbol: str,
    property: market_info_pb2.SymbolInfoIntegerProperty,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> int

Get individual symbol integer property.

Available properties:

SYMBOL_DIGITS               # Number of decimal places (5 for EURUSD)
SYMBOL_SPREAD               # Current spread in points
SYMBOL_TRADE_MODE           # Trade mode (0=disabled, 4=full)
SYMBOL_TRADE_EXEMODE        # Execution mode (instant/market/exchange)
SYMBOL_START_TIME           # Symbol start time (Unix timestamp)
SYMBOL_EXPIRATION_TIME      # Symbol expiration time (Unix timestamp)
SYMBOL_FILLING_MODE         # Filling mode flags
SYMBOL_ORDER_MODE           # Allowed order types flags

Returns: int value directly


8) get_symbol_string

async def get_symbol_string(
    self,
    symbol: str,
    property: market_info_pb2.SymbolInfoStringProperty,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> str

Get individual symbol string property.

Available properties:

SYMBOL_DESCRIPTION          # Symbol description ("Euro vs US Dollar")
SYMBOL_CURRENCY_BASE        # Base currency ("EUR" for EURUSD)
SYMBOL_CURRENCY_PROFIT      # Profit currency ("USD" for EURUSD)
SYMBOL_CURRENCY_MARGIN      # Margin currency
SYMBOL_BANK                 # Source of quotes
SYMBOL_ISIN                 # ISIN code
SYMBOL_CATEGORY             # Symbol category (Forex, Stocks, etc.)
SYMBOL_PATH                 # Path in symbol tree

Returns: str value directly


9) get_symbol_margin_rate

async def get_symbol_margin_rate(
    self,
    symbol: str,
    order_type: market_info_pb2.ENUM_ORDER_TYPE,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> SymbolMarginRate

Get margin rates for a symbol and order type.

Args: - symbol: Symbol name - order_type: Order type (BUY, SELL, etc.)

Returns: SymbolMarginRate dataclass with initial and maintenance rates


10) get_symbol_tick

async def get_symbol_tick(
    self,
    symbol: str,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> SymbolTick

Get current market prices for a symbol.

Returns: SymbolTick dataclass with time already converted to datetime

Technical: Low-level returns SymbolInfoTickData with Unix timestamp (data.time). This wrapper converts time field from Unix seconds to Python datetime via fromtimestamp().

Advantage: No manual timestamp conversion needed - just use tick.time as datetime object!


11) get_symbol_session_quote

async def get_symbol_session_quote(
    self,
    symbol: str,
    day_of_week: market_info_pb2.DayOfWeek,
    session_index: int,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> SessionTime

Get quote session times.

Args: - symbol: Symbol name - day_of_week: Day of the week (MONDAY, TUESDAY, etc.) - session_index: Session index (starting at 0, most symbols have 1 session)

Returns: SessionTime with start/end times as datetime

Technical: Low-level returns protobuf Timestamps. This wrapper converts both to Python datetimes via ToDatetime().


12) get_symbol_session_trade

async def get_symbol_session_trade(
    self,
    symbol: str,
    day_of_week: market_info_pb2.DayOfWeek,
    session_index: int,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> SessionTime

Get trading session times.

Args: - symbol: Symbol name - day_of_week: Day of the week - session_index: Session index (starting at 0)

Returns: SessionTime with start/end times as datetime

Usage: Shows when you can trade the symbol (different from quote session which shows when prices are updated).


13) get_symbol_params_many

async def get_symbol_params_many(
    self,
    name_filter: Optional[str] = None,
    sort_mode: Optional[int] = None,
    page_number: Optional[int] = None,
    items_per_page: Optional[int] = None,
    deadline: Optional[datetime] = None,
    cancellation_event: Optional[Any] = None,
) -> Tuple[List[SymbolParams], int]

Get parameters of multiple symbols at once.

Args: - name_filter: Optional symbol name filter (e.g., "EUR*" for all EUR pairs) - sort_mode: Optional sort mode - page_number: Optional page number for pagination - items_per_page: Optional items per page

Returns: Tuple[List[SymbolParams], total_count]

Technical: Low-level returns protobuf repeated field. This wrapper unpacks each SymbolInfo into SymbolParams dataclass with 17 fields.

Advantage: Much faster than 17 separate SymbolInfoDouble/Integer/String calls per symbol!


🔗 Usage Examples

Example 1: Getting Symbol Tick with Auto-Converted Time

async def monitor_tick(service: MT5Service, symbol: str):
    # Get tick - time is already datetime!
    tick = await service.get_symbol_tick(symbol)

    print(f"Symbol: {symbol}")
    print(f"Time: {tick.time.strftime('%Y-%m-%d %H:%M:%S')}")  # Already datetime
    print(f"Bid: {tick.bid:.5f}")
    print(f"Ask: {tick.ask:.5f}")
    print(f"Last: {tick.last:.5f}")
    print(f"Volume: {tick.volume}")

    # No manual timestamp conversion needed!

Example 2: Checking Symbol Availability

async def check_symbol(service: MT5Service, symbol: str):
    exists, is_custom = await service.symbol_exist(symbol)

    if not exists:
        print(f"Symbol {symbol} does not exist")
        return False

    if is_custom:
        print(f"{symbol} is a custom symbol")

    # Check if synchronized
    synced = await service.is_symbol_synchronized(symbol)
    if not synced:
        print(f"WARNING: {symbol} data is not synchronized")
        return False

    print(f"{symbol} is available and synchronized")
    return True

Example 3: Getting Trading Session Times

from MetaRpcMT5 import mt5_term_api_market_info_pb2 as market_info_pb2

async def check_trading_hours(service: MT5Service, symbol: str):
    """Check if symbol is currently in trading session."""

    from datetime import datetime

    now = datetime.now()
    day_of_week = market_info_pb2.DayOfWeek.Value(
        f"DAY_{now.strftime('%A').upper()}"
    )

    try:
        # Get trading session for today (session_index=0 for main session)
        session = await service.get_symbol_session_trade(
            symbol=symbol,
            day_of_week=day_of_week,
            session_index=0
        )

        print(f"Trading session for {symbol} today:")
        print(f"  From: {session.from_time.strftime('%H:%M:%S')}")
        print(f"  To: {session.to_time.strftime('%H:%M:%S')}")

        # Times are already datetime objects!
        if session.from_time <= now <= session.to_time:
            print("  Status: OPEN")
        else:
            print("  Status: CLOSED")

    except Exception as e:
        print(f"No trading session for {symbol} today: {e}")

Example 4: Bulk Symbol Data Retrieval (get_symbol_params_many)

async def get_all_eur_symbols(service: MT5Service):
    """Get comprehensive data for all EUR symbols efficiently."""

    # Get all symbols starting with "EUR" in one call
    symbols, total = await service.get_symbol_params_many(
        name_filter="EUR*",
        items_per_page=100
    )

    print(f"Found {total} EUR symbols\n")

    for sym in symbols:
        print(f"{sym.name}:")
        print(f"  Bid: {sym.bid:.5f}, Ask: {sym.ask:.5f}")
        print(f"  Spread: {sym.spread} points")
        print(f"  Digits: {sym.digits}")
        print(f"  Volume: {sym.volume_min} - {sym.volume_max} (step: {sym.volume_step})")
        print(f"  Contract size: {sym.trade_contract_size}")
        print(f"  Swap long/short: {sym.swap_long}/{sym.swap_short}")
        print()

    # This is MUCH faster than calling get_symbol_double/integer/string
    # 17 times for each symbol!

When to Use Which Method

Use get_symbol_tick()

Use when: - You need current Bid/Ask prices with timestamp - Want complete tick data in one call - Need time as datetime (auto-converted)

Example:

tick = await service.get_symbol_tick("EURUSD")
print(f"Bid: {tick.bid}, Time: {tick.time}")


Use get_symbol_double/integer/string()

Use when: - You need ONE specific property - Writing validation checks - Performance matters (single property faster than tick)

Example:

spread = await service.get_symbol_integer(
    "EURUSD", market_info_pb2.SYMBOL_SPREAD
)


Use get_symbol_params_many()

Use when: - You need data for MULTIPLE symbols - Building symbol scanner/screener - Need comprehensive symbol info (17 fields) - Want to minimize API calls

Example:

# Get all forex symbols at once
symbols, _ = await service.get_symbol_params_many(name_filter="*USD")

Advantage: 100x faster than individual calls for each symbol!


Recommendations

  1. For current prices + time - use get_symbol_tick() (Bid/Ask + datetime in one call, no manual unpacking)
  2. For multiple symbols - use get_symbol_params_many() (17 fields per symbol in one call - 100x faster!)
  3. For single property - use get_symbol_double/integer/string() (unpacks protobuf data.value for you)
  4. For session times - use get_symbol_session_quote/trade() (datetime conversion included)
  5. Before trading - always check with symbol_exist() and is_symbol_synchronized() (cleaner than manual protobuf)

Bottom line: Use MT5Service for all symbol operations - it unpacks protobuf Data objects and converts datetime automatically.



Summary

Real value for end users: - ALL 13 methods add value - MT5Account returns protobuf Data objects that need unpacking - get_symbol_params_many() - Aggregates 17 fields in one call (100x faster for multiple symbols) - get_symbol_tick() - Unix timestamp datetime + unpacks 8 fields - get_symbol_session_quote/trade() - Protobuf Timestamps datetime x2 - Other 9 methods - Protobuf unpacking (data.value native type)

Architectural layer (for MT5Sugar): - All methods used by MT5Sugar to maintain layered architecture (Sugar Service Account) - Provides unified interface with consistent naming (get_* prefix)

Key difference from Account methods: - Account methods: MT5Account already returns native types Service adds no value (just pass-through) - Symbol methods: MT5Account returns protobuf Data Service unpacks + converts real value

Recommendation: - Using MT5Sugar? These methods work seamlessly through the architecture - Using MT5Service directly? All methods add value - use them all! - High priority: get_symbol_params_many(), get_symbol_tick(), session methods - Medium priority: Other methods save you from manual protobuf unpacking