pdmt5 0.1.2__py3-none-any.whl → 0.1.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pdmt5/trading.py
CHANGED
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from
|
|
5
|
+
from datetime import timedelta
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
6
7
|
|
|
7
8
|
from pydantic import ConfigDict, Field
|
|
8
9
|
|
|
9
10
|
from .dataframe import Mt5DataClient
|
|
10
11
|
from .mt5 import Mt5RuntimeError
|
|
11
12
|
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
import pandas as pd
|
|
15
|
+
|
|
12
16
|
|
|
13
17
|
class Mt5TradingError(Mt5RuntimeError):
|
|
14
18
|
"""MetaTrader5 trading error."""
|
|
@@ -190,3 +194,178 @@ class Mt5TradingClient(Mt5DataClient):
|
|
|
190
194
|
f"Failed to calculate minimum order margins for symbol: {symbol}."
|
|
191
195
|
)
|
|
192
196
|
raise Mt5TradingError(error_message)
|
|
197
|
+
|
|
198
|
+
def calculate_spread_ratio(
|
|
199
|
+
self,
|
|
200
|
+
symbol: str,
|
|
201
|
+
) -> float:
|
|
202
|
+
"""Calculate the spread ratio for a given symbol.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
symbol: Symbol for which to calculate the spread ratio.
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
Spread ratio as a float.
|
|
209
|
+
"""
|
|
210
|
+
symbol_info_tick = self.symbol_info_tick_as_dict(symbol=symbol)
|
|
211
|
+
return (
|
|
212
|
+
(symbol_info_tick["ask"] - symbol_info_tick["bid"])
|
|
213
|
+
/ (symbol_info_tick["ask"] + symbol_info_tick["bid"])
|
|
214
|
+
* 2
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
def fetch_latest_rates_as_df(
|
|
218
|
+
self,
|
|
219
|
+
symbol: str,
|
|
220
|
+
granularity: str = "M1",
|
|
221
|
+
count: int = 1440,
|
|
222
|
+
index_keys: str | None = "time",
|
|
223
|
+
) -> pd.DataFrame:
|
|
224
|
+
"""Fetch rate (OHLC) data as a DataFrame.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
symbol: Symbol to fetch data for.
|
|
228
|
+
granularity: Time granularity as a timeframe suffix (e.g., "M1", "H1").
|
|
229
|
+
count: Number of bars to fetch.
|
|
230
|
+
index_keys: Optional index keys for the DataFrame.
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
pd.DataFrame: OHLC data with time index.
|
|
234
|
+
|
|
235
|
+
Raises:
|
|
236
|
+
Mt5TradingError: If the granularity is not supported by MetaTrader5.
|
|
237
|
+
"""
|
|
238
|
+
try:
|
|
239
|
+
timeframe = getattr(self.mt5, f"TIMEFRAME_{granularity.upper()}")
|
|
240
|
+
except AttributeError as e:
|
|
241
|
+
error_message = (
|
|
242
|
+
f"MetaTrader5 does not support the given granularity: {granularity}"
|
|
243
|
+
)
|
|
244
|
+
raise Mt5TradingError(error_message) from e
|
|
245
|
+
else:
|
|
246
|
+
return self.copy_rates_from_pos_as_df(
|
|
247
|
+
symbol=symbol,
|
|
248
|
+
timeframe=timeframe,
|
|
249
|
+
start_pos=0,
|
|
250
|
+
count=count,
|
|
251
|
+
index_keys=index_keys,
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
def fetch_latest_ticks_as_df(
|
|
255
|
+
self,
|
|
256
|
+
symbol: str,
|
|
257
|
+
seconds: int = 300,
|
|
258
|
+
index_keys: str | None = "time_msc",
|
|
259
|
+
) -> pd.DataFrame:
|
|
260
|
+
"""Fetch tick data as a DataFrame.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
symbol: Symbol to fetch tick data for.
|
|
264
|
+
seconds: Time range in seconds to fetch ticks around the last tick time.
|
|
265
|
+
index_keys: Optional index keys for the DataFrame.
|
|
266
|
+
|
|
267
|
+
Returns:
|
|
268
|
+
pd.DataFrame: Tick data with time index.
|
|
269
|
+
"""
|
|
270
|
+
last_tick_time = self.symbol_info_tick_as_dict(symbol=symbol)["time"]
|
|
271
|
+
return self.copy_ticks_range_as_df(
|
|
272
|
+
symbol=symbol,
|
|
273
|
+
date_from=(last_tick_time - timedelta(seconds=seconds)),
|
|
274
|
+
date_to=(last_tick_time + timedelta(seconds=seconds)),
|
|
275
|
+
flags=self.mt5.COPY_TICKS_ALL,
|
|
276
|
+
index_keys=index_keys,
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
def collect_entry_deals_as_df(
|
|
280
|
+
self,
|
|
281
|
+
symbol: str,
|
|
282
|
+
history_seconds: int = 3600,
|
|
283
|
+
index_keys: str | None = "ticket",
|
|
284
|
+
) -> pd.DataFrame:
|
|
285
|
+
"""Collect entry deals as a DataFrame.
|
|
286
|
+
|
|
287
|
+
Args:
|
|
288
|
+
symbol: Symbol to collect entry deals for.
|
|
289
|
+
history_seconds: Time range in seconds to fetch deals around the last tick.
|
|
290
|
+
index_keys: Optional index keys for the DataFrame.
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
pd.DataFrame: Entry deals with time index.
|
|
294
|
+
"""
|
|
295
|
+
last_tick_time = self.symbol_info_tick_as_dict(symbol=symbol)["time"]
|
|
296
|
+
deals_df = self.history_deals_get_as_df(
|
|
297
|
+
date_from=(last_tick_time - timedelta(seconds=history_seconds)),
|
|
298
|
+
date_to=(last_tick_time + timedelta(seconds=history_seconds)),
|
|
299
|
+
symbol=symbol,
|
|
300
|
+
index_keys=index_keys,
|
|
301
|
+
)
|
|
302
|
+
if deals_df.empty:
|
|
303
|
+
return deals_df
|
|
304
|
+
else:
|
|
305
|
+
return deals_df.pipe(
|
|
306
|
+
lambda d: d[
|
|
307
|
+
d["entry"]
|
|
308
|
+
& d["type"].isin({self.mt5.DEAL_TYPE_BUY, self.mt5.DEAL_TYPE_SELL})
|
|
309
|
+
]
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
def fetch_positions_with_metrics_as_df(
|
|
313
|
+
self,
|
|
314
|
+
symbol: str,
|
|
315
|
+
) -> pd.DataFrame:
|
|
316
|
+
"""Fetch open positions as a DataFrame with additional metrics.
|
|
317
|
+
|
|
318
|
+
Args:
|
|
319
|
+
symbol: Symbol to fetch positions for.
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
pd.DataFrame: DataFrame containing open positions with additional metrics.
|
|
323
|
+
"""
|
|
324
|
+
positions_df = self.positions_get_as_df(symbol=symbol)
|
|
325
|
+
if positions_df.empty:
|
|
326
|
+
return positions_df
|
|
327
|
+
else:
|
|
328
|
+
symbol_info_tick = self.symbol_info_tick_as_dict(symbol=symbol)
|
|
329
|
+
ask_margin = self.order_calc_margin(
|
|
330
|
+
action=self.mt5.ORDER_TYPE_BUY,
|
|
331
|
+
symbol=symbol,
|
|
332
|
+
volume=1,
|
|
333
|
+
price=symbol_info_tick["ask"],
|
|
334
|
+
)
|
|
335
|
+
bid_margin = self.order_calc_margin(
|
|
336
|
+
action=self.mt5.ORDER_TYPE_SELL,
|
|
337
|
+
symbol=symbol,
|
|
338
|
+
volume=1,
|
|
339
|
+
price=symbol_info_tick["bid"],
|
|
340
|
+
)
|
|
341
|
+
return (
|
|
342
|
+
positions_df.assign(
|
|
343
|
+
elapsed_seconds=lambda d: (
|
|
344
|
+
symbol_info_tick["time"] - d["time"]
|
|
345
|
+
).dt.total_seconds(),
|
|
346
|
+
underlier_increase_ratio=lambda d: (
|
|
347
|
+
d["price_current"] / d["price_open"] - 1
|
|
348
|
+
),
|
|
349
|
+
buy=lambda d: (d["type"] == self.mt5.POSITION_TYPE_BUY),
|
|
350
|
+
sell=lambda d: (d["type"] == self.mt5.POSITION_TYPE_SELL),
|
|
351
|
+
)
|
|
352
|
+
.assign(
|
|
353
|
+
buy_i=lambda d: d["buy"].astype(int),
|
|
354
|
+
sell_i=lambda d: d["sell"].astype(int),
|
|
355
|
+
)
|
|
356
|
+
.assign(
|
|
357
|
+
sign=lambda d: (d["buy_i"] - d["sell_i"]),
|
|
358
|
+
margin=lambda d: (
|
|
359
|
+
(d["buy_i"] * ask_margin + d["sell_i"] * bid_margin)
|
|
360
|
+
* d["volume"]
|
|
361
|
+
),
|
|
362
|
+
)
|
|
363
|
+
.assign(
|
|
364
|
+
signed_volume=lambda d: (d["volume"] * d["sign"]),
|
|
365
|
+
signed_margin=lambda d: (d["margin"] * d["sign"]),
|
|
366
|
+
underlier_profit_ratio=lambda d: (
|
|
367
|
+
d["underlier_increase_ratio"] * d["sign"]
|
|
368
|
+
),
|
|
369
|
+
)
|
|
370
|
+
.drop(columns=["buy_i", "sell_i", "sign", "underlier_increase_ratio"])
|
|
371
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pdmt5
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.4
|
|
4
4
|
Summary: Pandas-based data handler for MetaTrader 5
|
|
5
5
|
Project-URL: Repository, https://github.com/dceoy/pdmt5.git
|
|
6
6
|
Author-email: dceoy <dceoy@users.noreply.github.com>
|
|
@@ -29,6 +29,7 @@ Pandas-based data handler for MetaTrader 5
|
|
|
29
29
|
[](https://www.python.org/downloads/)
|
|
30
30
|
[](https://opensource.org/licenses/MIT)
|
|
31
31
|
[](https://www.microsoft.com/windows)
|
|
32
|
+
[](https://github.com/dceoy/pdmt5)
|
|
32
33
|
|
|
33
34
|
## Overview
|
|
34
35
|
|
|
@@ -78,14 +79,13 @@ config = Mt5Config(
|
|
|
78
79
|
login=12345678,
|
|
79
80
|
password="your_password",
|
|
80
81
|
server="YourBroker-Server",
|
|
81
|
-
timeout=60000
|
|
82
|
-
portable=False
|
|
82
|
+
timeout=60000
|
|
83
83
|
)
|
|
84
84
|
|
|
85
85
|
# Use as context manager
|
|
86
86
|
with Mt5DataClient(config=config) as client:
|
|
87
87
|
# Get account information as DataFrame
|
|
88
|
-
account_info = client.
|
|
88
|
+
account_info = client.account_info_as_df()
|
|
89
89
|
print(account_info)
|
|
90
90
|
|
|
91
91
|
# Get OHLCV data as DataFrame
|
|
@@ -98,7 +98,7 @@ with Mt5DataClient(config=config) as client:
|
|
|
98
98
|
print(rates.head())
|
|
99
99
|
|
|
100
100
|
# Get current positions as DataFrame
|
|
101
|
-
positions = client.
|
|
101
|
+
positions = client.positions_get_as_df()
|
|
102
102
|
print(positions)
|
|
103
103
|
```
|
|
104
104
|
|
|
@@ -106,34 +106,110 @@ with Mt5DataClient(config=config) as client:
|
|
|
106
106
|
|
|
107
107
|
### Mt5Client
|
|
108
108
|
|
|
109
|
-
The base client for
|
|
110
|
-
|
|
111
|
-
- **Connection Management**:
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
-
|
|
115
|
-
-
|
|
109
|
+
The base client wrapper for all MetaTrader5 operations with context manager support:
|
|
110
|
+
|
|
111
|
+
- **Connection Management**:
|
|
112
|
+
- `initialize()` - Establish connection with MT5 terminal (with optional path, login, password, server, timeout)
|
|
113
|
+
- `login()` - Connect to trading account with credentials
|
|
114
|
+
- `shutdown()` - Close MT5 terminal connection
|
|
115
|
+
- Context manager support (`with` statement) for automatic initialization/cleanup
|
|
116
|
+
- **Terminal Information**:
|
|
117
|
+
- `version()` - Get MT5 terminal version, build, and release date
|
|
118
|
+
- `last_error()` - Get last error code and description
|
|
119
|
+
- `account_info()` - Get current trading account information
|
|
120
|
+
- `terminal_info()` - Get terminal status and settings
|
|
121
|
+
- **Symbol Operations**:
|
|
122
|
+
- `symbols_total()` - Get total number of financial instruments
|
|
123
|
+
- `symbols_get()` - Get all symbols or filter by group
|
|
124
|
+
- `symbol_info()` - Get detailed data on specific symbol
|
|
125
|
+
- `symbol_info_tick()` - Get last tick for symbol
|
|
126
|
+
- `symbol_select()` - Show/hide symbol in MarketWatch
|
|
127
|
+
- **Market Depth**:
|
|
128
|
+
- `market_book_add()` - Subscribe to Market Depth events
|
|
129
|
+
- `market_book_get()` - Get current Market Depth data
|
|
130
|
+
- `market_book_release()` - Unsubscribe from Market Depth
|
|
131
|
+
- **Market Data**:
|
|
132
|
+
- `copy_rates_from()` - Get bars from specified date
|
|
133
|
+
- `copy_rates_from_pos()` - Get bars from specified position
|
|
134
|
+
- `copy_rates_range()` - Get bars for date range
|
|
135
|
+
- `copy_ticks_from()` - Get ticks from specified date
|
|
136
|
+
- `copy_ticks_range()` - Get ticks for date range
|
|
137
|
+
- **Order Operations**:
|
|
138
|
+
- `orders_total()` - Get number of active orders
|
|
139
|
+
- `orders_get()` - Get active orders with optional filters
|
|
140
|
+
- `order_calc_margin()` - Calculate required margin
|
|
141
|
+
- `order_calc_profit()` - Calculate potential profit
|
|
142
|
+
- `order_check()` - Check if order can be placed
|
|
143
|
+
- `order_send()` - Send order to trade server
|
|
144
|
+
- **Position Operations**:
|
|
145
|
+
- `positions_total()` - Get number of open positions
|
|
146
|
+
- `positions_get()` - Get open positions with optional filters
|
|
147
|
+
- **Trading History**:
|
|
148
|
+
- `history_orders_total()` - Get number of historical orders
|
|
149
|
+
- `history_orders_get()` - Get historical orders with filters
|
|
150
|
+
- `history_deals_total()` - Get number of historical deals
|
|
151
|
+
- `history_deals_get()` - Get historical deals with filters
|
|
116
152
|
|
|
117
153
|
### Mt5DataClient
|
|
118
154
|
|
|
119
|
-
Extends Mt5Client with pandas DataFrame conversions:
|
|
120
|
-
|
|
121
|
-
- **
|
|
122
|
-
-
|
|
123
|
-
-
|
|
124
|
-
- **
|
|
125
|
-
-
|
|
126
|
-
-
|
|
127
|
-
-
|
|
155
|
+
Extends Mt5Client with pandas DataFrame and dictionary conversions:
|
|
156
|
+
|
|
157
|
+
- **Enhanced Connection**:
|
|
158
|
+
- `initialize_and_login_mt5()` - Combined initialization and login with retry logic
|
|
159
|
+
- Configurable retry attempts via `retry_count` parameter
|
|
160
|
+
- **DataFrame/Dictionary Conversions**: All methods have both `_as_df` and `_as_dict` variants:
|
|
161
|
+
- `version_as_dict/df()` - MT5 version information
|
|
162
|
+
- `last_error_as_dict/df()` - Last error details
|
|
163
|
+
- `account_info_as_dict/df()` - Account information
|
|
164
|
+
- `terminal_info_as_dict/df()` - Terminal information
|
|
165
|
+
- `symbols_get_as_dicts/df()` - Symbol list with optional group filter
|
|
166
|
+
- `symbol_info_as_dict/df()` - Single symbol information
|
|
167
|
+
- `symbol_info_tick_as_dict/df()` - Last tick data
|
|
168
|
+
- `market_book_get_as_dicts/df()` - Market depth data
|
|
169
|
+
- **OHLCV Data Methods**:
|
|
170
|
+
- `copy_rates_from_as_dicts/df()` - Historical bars from date
|
|
171
|
+
- `copy_rates_from_pos_as_dicts/df()` - Historical bars from position
|
|
172
|
+
- `copy_rates_range_as_dicts/df()` - Historical bars for date range
|
|
173
|
+
- **Tick Data Methods**:
|
|
174
|
+
- `copy_ticks_from_as_dicts/df()` - Historical ticks from date
|
|
175
|
+
- `copy_ticks_range_as_dicts/df()` - Historical ticks for date range
|
|
176
|
+
- **Trading Data Methods**:
|
|
177
|
+
- `orders_get_as_dicts/df()` - Active orders with filters
|
|
178
|
+
- `order_check_as_dict/df()` - Order validation results
|
|
179
|
+
- `order_send_as_dict/df()` - Order execution results
|
|
180
|
+
- `positions_get_as_dicts/df()` - Open positions with filters
|
|
181
|
+
- `history_orders_get_as_dicts/df()` - Historical orders with date/ticket/position filters
|
|
182
|
+
- `history_deals_get_as_dicts/df()` - Historical deals with date/ticket/position filters
|
|
183
|
+
- **Features**:
|
|
184
|
+
- Automatic time conversion to datetime objects
|
|
185
|
+
- Optional DataFrame indexing with `index_keys` parameter
|
|
186
|
+
- Input validation for dates, counts, and positions
|
|
187
|
+
- Pydantic-based configuration via `Mt5Config`
|
|
128
188
|
|
|
129
189
|
### Mt5TradingClient
|
|
130
190
|
|
|
131
|
-
Advanced trading operations
|
|
132
|
-
|
|
133
|
-
- **
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
- **
|
|
191
|
+
Advanced trading operations client that extends Mt5DataClient:
|
|
192
|
+
|
|
193
|
+
- **Trading Configuration**:
|
|
194
|
+
- `order_filling_mode` - Order execution mode: "IOC" (default), "FOK", or "RETURN"
|
|
195
|
+
- `dry_run` - Test mode flag for simulating trades without execution
|
|
196
|
+
- **Position Management**:
|
|
197
|
+
- `close_open_positions()` - Close all positions for specified symbol(s)
|
|
198
|
+
- `send_or_check_order()` - Execute or validate orders based on dry_run mode
|
|
199
|
+
- **Market Analysis**:
|
|
200
|
+
- `calculate_minimum_order_margins()` - Calculate minimum required margins for buy/sell orders
|
|
201
|
+
- `calculate_spread_ratio()` - Calculate normalized bid-ask spread ratio
|
|
202
|
+
- **Simplified Data Access**:
|
|
203
|
+
- `fetch_latest_rates_as_df()` - Get recent OHLC data with timeframe strings (e.g., "M1", "H1", "D1")
|
|
204
|
+
- `fetch_latest_ticks_as_df()` - Get tick data for specified seconds around last tick
|
|
205
|
+
- `collect_entry_deals_as_df()` - Filter and collect entry deals (BUY/SELL) from history
|
|
206
|
+
- `fetch_positions_with_metrics_as_df()` - Get open positions with calculated metrics (elapsed time, margin, profit ratios)
|
|
207
|
+
- **Features**:
|
|
208
|
+
- Smart order routing with configurable filling modes
|
|
209
|
+
- Comprehensive error handling with `Mt5TradingError`
|
|
210
|
+
- Support for batch operations on multiple symbols
|
|
211
|
+
- Automatic position closing with proper order type reversal
|
|
212
|
+
- Dry run mode for strategy testing without real trades
|
|
137
213
|
|
|
138
214
|
### Configuration
|
|
139
215
|
|
|
@@ -144,8 +220,7 @@ config = Mt5Config(
|
|
|
144
220
|
login=12345678, # MT5 account number
|
|
145
221
|
password="password", # MT5 password
|
|
146
222
|
server="Broker-Server", # MT5 server name
|
|
147
|
-
timeout=60000
|
|
148
|
-
portable=False # Use portable mode
|
|
223
|
+
timeout=60000 # Connection timeout in ms
|
|
149
224
|
)
|
|
150
225
|
```
|
|
151
226
|
|
|
@@ -194,7 +269,7 @@ with Mt5DataClient(config=config) as client:
|
|
|
194
269
|
```python
|
|
195
270
|
with Mt5DataClient(config=config) as client:
|
|
196
271
|
# Get all open positions as DataFrame
|
|
197
|
-
positions = client.
|
|
272
|
+
positions = client.positions_get_as_df()
|
|
198
273
|
|
|
199
274
|
if not positions.empty:
|
|
200
275
|
# Calculate summary statistics
|
|
@@ -227,6 +302,50 @@ with Mt5TradingClient(config=config, order_filling_mode="IOC") as trader:
|
|
|
227
302
|
test_results = trader_dry.close_open_positions(symbols=["EURUSD", "GBPUSD"])
|
|
228
303
|
```
|
|
229
304
|
|
|
305
|
+
### Market Analysis with Mt5TradingClient
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
with Mt5TradingClient(config=config) as trader:
|
|
309
|
+
# Calculate spread ratio for EURUSD
|
|
310
|
+
spread_ratio = trader.calculate_spread_ratio("EURUSD")
|
|
311
|
+
print(f"EURUSD spread ratio: {spread_ratio:.5f}")
|
|
312
|
+
|
|
313
|
+
# Get minimum order margins
|
|
314
|
+
margins = trader.calculate_minimum_order_margins("EURUSD")
|
|
315
|
+
print(f"Minimum ask margin: {margins['ask']}")
|
|
316
|
+
print(f"Minimum bid margin: {margins['bid']}")
|
|
317
|
+
|
|
318
|
+
# Get recent OHLC data with custom timeframe
|
|
319
|
+
rates_df = trader.fetch_latest_rates_as_df(
|
|
320
|
+
symbol="EURUSD",
|
|
321
|
+
granularity="M15", # 15-minute bars
|
|
322
|
+
count=100
|
|
323
|
+
)
|
|
324
|
+
print(rates_df.tail())
|
|
325
|
+
|
|
326
|
+
# Get tick data for the last 60 seconds
|
|
327
|
+
ticks_df = trader.fetch_latest_ticks_as_df(
|
|
328
|
+
symbol="EURUSD",
|
|
329
|
+
seconds=60
|
|
330
|
+
)
|
|
331
|
+
print(f"Received {len(ticks_df)} ticks")
|
|
332
|
+
|
|
333
|
+
# Collect entry deals for the last hour
|
|
334
|
+
deals_df = trader.collect_entry_deals_as_df(
|
|
335
|
+
symbol="EURUSD",
|
|
336
|
+
history_seconds=3600
|
|
337
|
+
)
|
|
338
|
+
if not deals_df.empty:
|
|
339
|
+
print(f"Found {len(deals_df)} entry deals")
|
|
340
|
+
print(deals_df[['time', 'type', 'volume', 'price']].head())
|
|
341
|
+
|
|
342
|
+
# Get positions with calculated metrics
|
|
343
|
+
positions_df = trader.fetch_positions_with_metrics_as_df("EURUSD")
|
|
344
|
+
if not positions_df.empty:
|
|
345
|
+
print(f"Open positions with metrics:")
|
|
346
|
+
print(positions_df[['ticket', 'volume', 'profit', 'elapsed_seconds', 'underlier_profit_ratio']].head())
|
|
347
|
+
```
|
|
348
|
+
|
|
230
349
|
## Development
|
|
231
350
|
|
|
232
351
|
### Setup Development Environment
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
pdmt5/__init__.py,sha256=QbSFrsi7_bgFzb-ma4DmmUjR90UvrqKMnRZq1wPRmoI,446
|
|
2
2
|
pdmt5/dataframe.py,sha256=rUWtR23hrXBdBqzJhbOlIemNy73RrjSTZZJUhwoL6io,38084
|
|
3
3
|
pdmt5/mt5.py,sha256=KgxHapIrh5b4L0wIOAQIjfXNZafalihbFrh9fhYHmrI,32254
|
|
4
|
-
pdmt5/trading.py,sha256=
|
|
4
|
+
pdmt5/trading.py,sha256=qZFORyBlSQNp_DQPeuEIqFHPAnVrCJK_6GhFRc5vDR8,13683
|
|
5
5
|
pdmt5/utils.py,sha256=Ll5Q3OE5h1A_sZ_qVEnOPGniFlT6_MmHfuu0zqeLdeU,3913
|
|
6
|
-
pdmt5-0.1.
|
|
7
|
-
pdmt5-0.1.
|
|
8
|
-
pdmt5-0.1.
|
|
9
|
-
pdmt5-0.1.
|
|
6
|
+
pdmt5-0.1.4.dist-info/METADATA,sha256=XFIW5O6a7bePMxnDVc7MG6mnkXwNTY_53_mVb_BJxnY,14678
|
|
7
|
+
pdmt5-0.1.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
8
|
+
pdmt5-0.1.4.dist-info/licenses/LICENSE,sha256=iABrdaUGOBWLYotFupB_PGe8arV5o7rVhn-_vK6P704,1073
|
|
9
|
+
pdmt5-0.1.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|