✅ 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— methodon_position_profit(...)MetaRpcMT5/mt5_term_api_subscriptions_pb2.py—OnPositionProfit*messages and payloadsMetaRpcMT5/mt5_term_api_subscriptions_pb2_grpc.py— service stubSubscriptionServiceStub
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_mscontrols server timer; don’t spam with tiny intervals unless you really need it. ignore_empty=Truesuppresses 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 yieldsOnPositionProfitDataobjects 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)