Skip to content

✅ On Position Profit

Request: subscribe to periodic position P/L updates. Server‑streaming RPC that emits batches of new/updated/deleted positions plus an account P/L snapshot.

Source files (SDK):

  • MetaRpcMT5/mt5_account.py — method on_position_profit(...)
  • MetaRpcMT5/mt5_term_api_subscriptions_pb2.pyOnPositionProfit* messages and payloads
  • MetaRpcMT5/mt5_term_api_subscriptions_pb2_grpc.py — service stub SubscriptionServiceStub

RPC

  • Service: mt5_term_api.SubscriptionService
  • Method: OnPositionProfit(OnPositionProfitRequest) → stream OnPositionProfitReply
  • Low‑level client: SubscriptionServiceStub.OnPositionProfit(request, metadata, timeout) (server‑streaming iterator)
  • SDK wrapper: MT5Account.on_position_profit(interval_ms, ignore_empty, cancellation_event=None) → async stream of OnPositionProfitData

🔗 Code Example

# Minimal: stream profit updates every 1s, skip empty batches
async for ev in acct.on_position_profit(interval_ms=1000, ignore_empty=True):
    # ev: OnPositionProfitData
    total = sum(p.profit for p in (getattr(ev, 'updated_positions', []) or []))
    print("updated:", len(getattr(ev, 'updated_positions', []) or []), "total pnl:", total)
# With cooperative cancellation after first non‑empty event
import asyncio
cancel = asyncio.Event()

async for ev in acct.on_position_profit(500, True, cancellation_event=cancel):
    if (getattr(ev, 'new_positions', None) or getattr(ev, 'updated_positions', None) or getattr(ev, 'deleted_positions', None)):
        print("non‑empty batch; equity:", getattr(ev, 'account_info', None).equity)
        cancel.set()

Method Signature

async def on_position_profit(
    self,
    interval_ms: int,
    ignore_empty: bool,
    cancellation_event: asyncio.Event | None = None,
) -> AsyncIterator[subscription_pb2.OnPositionProfitData]

💬 Just about the main thing

  • What it is. Timed profit snapshots for positions with deltas (new/updated/deleted) and an account P/L frame.
  • Why. Keep dashboards, badges, and risk widgets fresh without polling multiple services.
  • Be careful.

  • interval_ms controls server timer; don’t spam with tiny intervals unless you really need it.

  • ignore_empty=True suppresses empty frames (no position changes) to reduce UI churn.

🔽 Input

Parameter Type Description
interval_ms int (required) Sampling period in milliseconds (server timer).
ignore_empty bool (required) Skip frames with no changes (positions lists empty).
cancellation_event `asyncio.Event None` Cooperative stop for the streaming RPC.

Request message: OnPositionProfitRequest { timerPeriodMilliseconds: int32, ignoreEmptyData: bool }


⬆️ Output

Stream payload: OnPositionProfitData

Field Proto Type Description
type MT5_SUB_ENUM_EVENT_GROUP_TYPE Event group marker (e.g., OrderProfit).
new_positions repeated OnPositionProfitPositionInfo Positions that appeared since last frame.
updated_positions repeated OnPositionProfitPositionInfo Positions with profit change/update.
deleted_positions repeated OnPositionProfitPositionInfo Positions that disappeared (closed).
account_info OnEventAccountInfo Account snapshot (balance/equity/margins).
terminal_instance_guid_id string Source terminal GUID.

OnPositionProfitPositionInfo

# Field Type Notes
1 index int32 Ordering index inside the batch.
2 ticket int64 Position ticket.
3 profit double Position profit at this snapshot.
4 position_symbol string Symbol of the position.

OnEventAccountInfo

# Field Type
1 balance double
2 credit double
3 equity double
4 margin double
5 free_margin double
6 profit double
7 margin_level double
8 login int64

Wire stream: OnPositionProfitReply { data: OnPositionProfitData, error?: Error } SDK wrapper yields OnPositionProfitData objects one by one.


Enum: MT5_SUB_ENUM_EVENT_GROUP_TYPE

Number Value
0 OrderProfit
1 OrderUpdate

🎯 Purpose

  • Drive P/L tickers and summary tiles in UI.
  • Alert on unusual profit swings per position.
  • Lightweight input for risk dashboards and telemetry.

🧩 Notes & Tips

  • For orders/positions life‑cycle deltas (beyond profit), see OnTrade.
  • For low-level transaction auditing (request/result), see OnTradeTransaction.
  • Use symbol_info_* calls to enrich rows with digits/format if you render money values.

See also: opened_orders.md, positions_history.md, on_trade.md

Usage Examples

1) Running sum of current P/L

async for ev in acct.on_position_profit(1000, True):
    pnl = sum(p.profit for p in (ev.updated_positions or []))
    print("P/L:", pnl)

2) Only show non-empty frames

async for ev in acct.on_position_profit(500, True):
    if not (ev.new_positions or ev.updated_positions or ev.deleted_positions):
        continue
    print("changed:", len(ev.new_positions), len(ev.updated_positions), len(ev.deleted_positions))

3) Stop the stream after 5 seconds

import asyncio
stop = asyncio.Event()
async def guard():
    await asyncio.sleep(5)
    stop.set()
asyncio.create_task(guard())

async for ev in acct.on_position_profit(200, False, cancellation_event=stop):
    print(ev.account_info.equity)