Skip to content

Deal Info

CDealInfo

Source code in strategytester5\trade_classes\DealInfo.py
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
class CDealInfo:
    def __init__(self, deal: TradeDeal, terminal: Union[OverLoadedMetaTrader5API|MetaTrader5]):
        """
        A lightweight Python wrapper that resembles the MQL5 Standard Library class
        `CDealInfo` and provides convenient, read-only access to MetaTrader 5 deal
        properties.

        [MQL5 Reference](https://www.mql5.com/en/docs/standardlibrary/tradeclasses/cdealinfo)

        Parameters
        ----------

        deal (tuple) : A deal object (e.g., from `mt5.history_deals_get()`) to wrap and provide access to.

        terminal (optional) : Native MetaTrader5 API or the simulated one.

        Notes
        -----
        - Many getters return `None` if no deal is selected.
        - Times:
            * `time` returns a timezone-aware UTC datetime (recommended for MT5 history).
            * `time_msc` returns milliseconds since 1970-01-01 (UTC) when available.
        - This wrapper does not modify terminal state; it only reads/derives properties.
        """

        self.terminal = terminal.mt5_instance
        self._deal = deal

        if self._deal is None:
            raise ValueError("Deal cannot be None. Please provide a valid deal tuple.")

    @property
    def deal_type_description(self):
        """Gets the deal type as a string"""

        if not self._deal:
            return "N/A"

        deal_type_map = {
            self.terminal.DEAL_TYPE_BUY: "BUY",
            self.terminal.DEAL_TYPE_SELL: "SELL",
            self.terminal.DEAL_TYPE_BALANCE: "BALANCE",
            self.terminal.DEAL_TYPE_CREDIT: "CREDIT",
            self.terminal.DEAL_TYPE_CHARGE: "CHARGE",
            self.terminal.DEAL_TYPE_CORRECTION: "CORRECTION",
            self.terminal.DEAL_TYPE_BONUS: "BONUS",
            self.terminal.DEAL_TYPE_COMMISSION: "COMMISSION",
            self.terminal.DEAL_TYPE_COMMISSION_DAILY: "COMMISSION DAILY",
            self.terminal.DEAL_TYPE_COMMISSION_MONTHLY: "COMMISSION MONTHLY",
            self.terminal.DEAL_TYPE_COMMISSION_AGENT_DAILY: "AGENT COMMISSION DAILY",
            self.terminal.DEAL_TYPE_COMMISSION_AGENT_MONTHLY: "AGENT COMMISSION MONTHLY",
            self.terminal.DEAL_TYPE_INTEREST: "INTEREST",
            self.terminal.DEAL_TYPE_BUY_CANCELED: "BUY CANCELED",
            self.terminal.DEAL_TYPE_SELL_CANCELED: "SELL CANCELED"
        }

        return deal_type_map.get(self._deal.type, f"UNKNOWN({self._deal.type})")

    @property
    def entry_description(self):
        """Gets the deal direction as a string"""

        if not self._deal:
            return "N/A"

        entry_map = {
            self.terminal.DEAL_ENTRY_IN: "IN",
            self.terminal.DEAL_ENTRY_OUT: "OUT",
            self.terminal.DEAL_ENTRY_INOUT: "INOUT"
        }

        return entry_map.get(self._deal.entry, "UNKNOWN")

    # --- Integer, datetime & properties

    @property
    def ticket(self) -> Optional[int]:
        """Gets ticket/selects the deal ticket."""
        return None if self._deal is None else int(self._deal.ticket)

    @property
    def order(self) -> Optional[int]:
        """Gets the order by which the deal was executed."""
        return None if self._deal is None else int(self._deal.order)

    @property
    def time(self) -> Optional[datetime]:
        """
        Gets the time of deal execution as a timezone-aware UTC datetime.

        Returns
        -------
        Optional[datetime]
            UTC datetime, or None if no deal is selected.
        """
        if self._deal is None:
            return None
        # MT5 history times are effectively UTC; keep it explicit.
        return datetime.fromtimestamp(int(self._deal.time), tz=timezone.utc)

    @property
    def time_msc(self) -> Optional[int]:
        """Receives the time of a deal execution in milliseconds since 1970-01-01 (UTC)."""
        return None if self._deal is None else int(self._deal.time_msc)

    @property
    def deal_type(self) -> Optional[int]:
        """Gets the deal type (DEAL_TYPE_*)."""
        return None if self._deal is None else int(self._deal.type)

    @property
    def type_description(self) -> str:
        """Gets the deal type as a string."""

        if self._deal is None:
            return "N/A"

        deal_type_map ={
            self.terminal.DEAL_TYPE_BUY: "BUY",
            self.terminal.DEAL_TYPE_SELL: "SELL",
            self.terminal.DEAL_TYPE_BALANCE: "BALANCE",
            self.terminal.DEAL_TYPE_CREDIT: "CREDIT",
            self.terminal.DEAL_TYPE_CHARGE: "CHARGE",
            self.terminal.DEAL_TYPE_CORRECTION: "CORRECTION",
            self.terminal.DEAL_TYPE_BONUS: "BONUS",
            self.terminal.DEAL_TYPE_COMMISSION: "COMMISSION",
            self.terminal.DEAL_TYPE_COMMISSION_DAILY: "COMMISSION DAILY",
            self.terminal.DEAL_TYPE_COMMISSION_MONTHLY: "COMMISSION MONTHLY",
            self.terminal.DEAL_TYPE_COMMISSION_AGENT_DAILY: "AGENT COMMISSION DAILY",
            self.terminal.DEAL_TYPE_COMMISSION_AGENT_MONTHLY: "AGENT COMMISSION MONTHLY",
            self.terminal.DEAL_TYPE_INTEREST: "INTEREST",
            self.terminal.DEAL_TYPE_BUY_CANCELED: "BUY CANCELED",
            self.terminal.DEAL_TYPE_SELL_CANCELED: "SELL CANCELED",
        }

        return deal_type_map.get(self._deal.type, f"UNKNOWN({self._deal.type})")

    @property
    def entry(self) -> Optional[int]:
        """Gets the deal direction/entry (DEAL_ENTRY_*)."""
        return None if self._deal is None else int(self._deal.entry)

    @property
    def magic(self) -> Optional[int]:
        """Gets the ID of the expert (magic number) that executed the deal."""
        return None if self._deal is None else int(self._deal.magic)

    @property
    def position_id(self) -> Optional[int]:
        """Gets the ID of the position in which the deal was involved."""
        return None if self._deal is None else int(self._deal.position_id)

    # Double properties

    @property
    def volume(self) -> Optional[float]:
        """Gets the volume of the deal."""
        return None if self._deal is None else float(self._deal.volume)

    @property
    def price(self) -> Optional[float]:
        """Gets the deal price."""
        return None if self._deal is None else float(self._deal.price)

    @property
    def commission(self) -> Optional[float]:
        """Gets the amount of commission for the deal."""
        return None if self._deal is None else float(self._deal.commission)

    @property
    def swap(self) -> Optional[float]:
        """Gets the amount of swap when the position is closed."""
        return None if self._deal is None else float(self._deal.swap)

    @property
    def profit(self) -> Optional[float]:
        """Gets the financial result of the deal."""
        return None if self._deal is None else float(self._deal.profit)

    # Text properties

    @property
    def symbol(self) -> Optional[str]:
        """Gets the symbol name."""
        return None if self._deal is None else str(self._deal.symbol)

    @property
    def comment(self) -> Optional[str]:
        """Gets the deal comment."""
        return None if self._deal is None else str(self._deal.comment)

    @property
    def external_id(self) -> Optional[str]:
        """Gets the external ID (if provided by the broker)."""
        return None if self._deal is None else str(self._deal.external_id)

    # -------------------------
    # Generic "Info*" methods (MQL5-like)
    # -------------------------

    def info_integer(self, prop_name: str) -> Optional[int]:
        """
        Gets an integer property value by attribute name.

        This is a Pythonic approximation of MQL5's InfoInteger/HistoryDealGetInteger.
        In Python MT5, deal objects expose fields as attributes.

        Parameters
        ----------
        prop_name : str
            Attribute name on the deal object (e.g., "ticket", "order", "magic").

        Returns
        -------
        Optional[int]
            The integer value, or None if no deal is selected or attribute missing.
        """
        if self._deal is None or not hasattr(self._deal, prop_name):
            return None
        value = getattr(self._deal, prop_name)
        return None if value is None else int(value)

    def info_double(self, prop_name: str) -> Optional[float]:
        """
        Gets a float property value by attribute name.

        Parameters
        ----------
        prop_name : str
            Attribute name on the deal object (e.g., "price", "profit", "volume").

        Returns
        -------
        Optional[float]
            The float value, or None if no deal is selected or attribute missing.
        """
        if self._deal is None or not hasattr(self._deal, prop_name):
            return None
        value = getattr(self._deal, prop_name)
        return None if value is None else float(value)

    def info_string(self, prop_name: str) -> Optional[str]:
        """
        Gets a string property value by attribute name.

        Parameters
        ----------
        prop_name : str
            Attribute name on the deal object (e.g., "symbol", "comment", "external_id").

        Returns
        -------
        Optional[str]
            The string value, or None if no deal is selected or attribute missing.
        """
        if self._deal is None or not hasattr(self._deal, prop_name):
            return None
        value = getattr(self._deal, prop_name)
        return None if value is None else str(value)

    def print_all(self) -> None:
        """Print all @property values of the class."""

        for name, attr in vars(type(self)).items():
            if isinstance(attr, property):
                try:
                    value = getattr(self, name)
                except Exception as e:
                    value = f"<error: {e}>"

                print(f"{name:20} : {value}")

comment property

Gets the deal comment.

commission property

Gets the amount of commission for the deal.

deal_type property

Gets the deal type (DEAL_TYPE_*).

deal_type_description property

Gets the deal type as a string

entry property

Gets the deal direction/entry (DEAL_ENTRY_*).

entry_description property

Gets the deal direction as a string

external_id property

Gets the external ID (if provided by the broker).

magic property

Gets the ID of the expert (magic number) that executed the deal.

order property

Gets the order by which the deal was executed.

position_id property

Gets the ID of the position in which the deal was involved.

price property

Gets the deal price.

profit property

Gets the financial result of the deal.

swap property

Gets the amount of swap when the position is closed.

symbol property

Gets the symbol name.

ticket property

Gets ticket/selects the deal ticket.

time property

Gets the time of deal execution as a timezone-aware UTC datetime.

Returns

Optional[datetime] UTC datetime, or None if no deal is selected.

time_msc property

Receives the time of a deal execution in milliseconds since 1970-01-01 (UTC).

type_description property

Gets the deal type as a string.

volume property

Gets the volume of the deal.

__init__(deal, terminal)

A lightweight Python wrapper that resembles the MQL5 Standard Library class CDealInfo and provides convenient, read-only access to MetaTrader 5 deal properties.

MQL5 Reference

Parameters

deal (tuple) : A deal object (e.g., from mt5.history_deals_get()) to wrap and provide access to.

terminal (optional) : Native MetaTrader5 API or the simulated one.

Notes
  • Many getters return None if no deal is selected.
  • Times:
    • time returns a timezone-aware UTC datetime (recommended for MT5 history).
    • time_msc returns milliseconds since 1970-01-01 (UTC) when available.
  • This wrapper does not modify terminal state; it only reads/derives properties.
Source code in strategytester5\trade_classes\DealInfo.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def __init__(self, deal: TradeDeal, terminal: Union[OverLoadedMetaTrader5API|MetaTrader5]):
    """
    A lightweight Python wrapper that resembles the MQL5 Standard Library class
    `CDealInfo` and provides convenient, read-only access to MetaTrader 5 deal
    properties.

    [MQL5 Reference](https://www.mql5.com/en/docs/standardlibrary/tradeclasses/cdealinfo)

    Parameters
    ----------

    deal (tuple) : A deal object (e.g., from `mt5.history_deals_get()`) to wrap and provide access to.

    terminal (optional) : Native MetaTrader5 API or the simulated one.

    Notes
    -----
    - Many getters return `None` if no deal is selected.
    - Times:
        * `time` returns a timezone-aware UTC datetime (recommended for MT5 history).
        * `time_msc` returns milliseconds since 1970-01-01 (UTC) when available.
    - This wrapper does not modify terminal state; it only reads/derives properties.
    """

    self.terminal = terminal.mt5_instance
    self._deal = deal

    if self._deal is None:
        raise ValueError("Deal cannot be None. Please provide a valid deal tuple.")

info_double(prop_name)

Gets a float property value by attribute name.

Parameters

prop_name : str Attribute name on the deal object (e.g., "price", "profit", "volume").

Returns

Optional[float] The float value, or None if no deal is selected or attribute missing.

Source code in strategytester5\trade_classes\DealInfo.py
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
def info_double(self, prop_name: str) -> Optional[float]:
    """
    Gets a float property value by attribute name.

    Parameters
    ----------
    prop_name : str
        Attribute name on the deal object (e.g., "price", "profit", "volume").

    Returns
    -------
    Optional[float]
        The float value, or None if no deal is selected or attribute missing.
    """
    if self._deal is None or not hasattr(self._deal, prop_name):
        return None
    value = getattr(self._deal, prop_name)
    return None if value is None else float(value)

info_integer(prop_name)

Gets an integer property value by attribute name.

This is a Pythonic approximation of MQL5's InfoInteger/HistoryDealGetInteger. In Python MT5, deal objects expose fields as attributes.

Parameters

prop_name : str Attribute name on the deal object (e.g., "ticket", "order", "magic").

Returns

Optional[int] The integer value, or None if no deal is selected or attribute missing.

Source code in strategytester5\trade_classes\DealInfo.py
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
def info_integer(self, prop_name: str) -> Optional[int]:
    """
    Gets an integer property value by attribute name.

    This is a Pythonic approximation of MQL5's InfoInteger/HistoryDealGetInteger.
    In Python MT5, deal objects expose fields as attributes.

    Parameters
    ----------
    prop_name : str
        Attribute name on the deal object (e.g., "ticket", "order", "magic").

    Returns
    -------
    Optional[int]
        The integer value, or None if no deal is selected or attribute missing.
    """
    if self._deal is None or not hasattr(self._deal, prop_name):
        return None
    value = getattr(self._deal, prop_name)
    return None if value is None else int(value)

info_string(prop_name)

Gets a string property value by attribute name.

Parameters

prop_name : str Attribute name on the deal object (e.g., "symbol", "comment", "external_id").

Returns

Optional[str] The string value, or None if no deal is selected or attribute missing.

Source code in strategytester5\trade_classes\DealInfo.py
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
def info_string(self, prop_name: str) -> Optional[str]:
    """
    Gets a string property value by attribute name.

    Parameters
    ----------
    prop_name : str
        Attribute name on the deal object (e.g., "symbol", "comment", "external_id").

    Returns
    -------
    Optional[str]
        The string value, or None if no deal is selected or attribute missing.
    """
    if self._deal is None or not hasattr(self._deal, prop_name):
        return None
    value = getattr(self._deal, prop_name)
    return None if value is None else str(value)

print_all()

Print all @property values of the class.

Source code in strategytester5\trade_classes\DealInfo.py
270
271
272
273
274
275
276
277
278
279
280
def print_all(self) -> None:
    """Print all @property values of the class."""

    for name, attr in vars(type(self)).items():
        if isinstance(attr, property):
            try:
                value = getattr(self, name)
            except Exception as e:
                value = f"<error: {e}>"

            print(f"{name:20} : {value}")