bbstrader 0.3.0__py3-none-any.whl → 0.3.2__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.
Potentially problematic release.
This version of bbstrader might be problematic. Click here for more details.
- bbstrader/__init__.py +1 -1
- bbstrader/__main__.py +19 -13
- bbstrader/btengine/backtest.py +7 -8
- bbstrader/btengine/execution.py +2 -2
- bbstrader/btengine/strategy.py +68 -17
- bbstrader/config.py +2 -2
- bbstrader/core/data.py +92 -29
- bbstrader/metatrader/account.py +81 -16
- bbstrader/metatrader/copier.py +594 -195
- bbstrader/metatrader/risk.py +1 -0
- bbstrader/metatrader/scripts.py +53 -13
- bbstrader/metatrader/trade.py +79 -67
- bbstrader/metatrader/utils.py +3 -0
- bbstrader/models/__init__.py +0 -1
- bbstrader/models/ml.py +55 -26
- bbstrader/models/nlp.py +182 -74
- bbstrader/models/optimization.py +1 -1
- bbstrader/models/risk.py +16 -386
- bbstrader/trading/execution.py +70 -41
- bbstrader/trading/strategies.py +9 -592
- bbstrader/tseries.py +39 -709
- {bbstrader-0.3.0.dist-info → bbstrader-0.3.2.dist-info}/METADATA +36 -44
- bbstrader-0.3.2.dist-info/RECORD +47 -0
- bbstrader-0.3.0.dist-info/RECORD +0 -47
- {bbstrader-0.3.0.dist-info → bbstrader-0.3.2.dist-info}/WHEEL +0 -0
- {bbstrader-0.3.0.dist-info → bbstrader-0.3.2.dist-info}/entry_points.txt +0 -0
- {bbstrader-0.3.0.dist-info → bbstrader-0.3.2.dist-info}/licenses/LICENSE +0 -0
- {bbstrader-0.3.0.dist-info → bbstrader-0.3.2.dist-info}/top_level.txt +0 -0
bbstrader/metatrader/account.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import re
|
|
3
3
|
import urllib.request
|
|
4
|
-
from datetime import datetime
|
|
4
|
+
from datetime import datetime, timedelta
|
|
5
5
|
from typing import Any, Dict, List, Literal, Optional, Tuple, Union
|
|
6
6
|
|
|
7
7
|
import pandas as pd
|
|
@@ -54,9 +54,7 @@ BROKERS_TIMEZONES = {
|
|
|
54
54
|
"PGL": "Europe/Helsinki",
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
_ADMIRAL_MARKETS_URL_ =
|
|
58
|
-
"https://cabinet.a-partnership.com/visit/?bta=35537&brand=admiralmarkets"
|
|
59
|
-
)
|
|
57
|
+
_ADMIRAL_MARKETS_URL_ = "https://one.justmarkets.link/a/tufvj0xugm/registration/trader"
|
|
60
58
|
_JUST_MARKETS_URL_ = "https://one.justmarkets.link/a/tufvj0xugm/registration/trader"
|
|
61
59
|
_FTMO_URL_ = "https://trader.ftmo.com/?affiliates=JGmeuQqepAZLMcdOEQRp"
|
|
62
60
|
_ADMIRAL_MARKETS_PRODUCTS_ = [
|
|
@@ -138,13 +136,13 @@ AMG_EXCHANGES = {
|
|
|
138
136
|
}
|
|
139
137
|
|
|
140
138
|
|
|
141
|
-
def check_mt5_connection(**kwargs):
|
|
139
|
+
def check_mt5_connection(**kwargs) -> bool:
|
|
142
140
|
"""
|
|
143
141
|
Initialize the connection to the MetaTrader 5 terminal.
|
|
144
142
|
|
|
145
143
|
Args:
|
|
146
144
|
path (str, optional): The path to the MetaTrader 5 terminal executable file.
|
|
147
|
-
Defaults to None (e.g., "C
|
|
145
|
+
Defaults to None (e.g., "C:/Program Files/MetaTrader 5/terminal64.exe").
|
|
148
146
|
login (int, optional): The login ID of the trading account. Defaults to None.
|
|
149
147
|
password (str, optional): The password of the trading account. Defaults to None.
|
|
150
148
|
server (str, optional): The name of the trade server to which the client terminal is connected.
|
|
@@ -165,6 +163,7 @@ def check_mt5_connection(**kwargs):
|
|
|
165
163
|
timeout = kwargs.get("timeout", 60_000)
|
|
166
164
|
portable = kwargs.get("portable", False)
|
|
167
165
|
|
|
166
|
+
init = False
|
|
168
167
|
if path is None and (login or password or server):
|
|
169
168
|
raise ValueError(
|
|
170
169
|
"You must provide a path to the terminal executable file"
|
|
@@ -189,6 +188,7 @@ def check_mt5_connection(**kwargs):
|
|
|
189
188
|
raise_mt5_error(INIT_MSG)
|
|
190
189
|
except Exception:
|
|
191
190
|
raise_mt5_error(INIT_MSG)
|
|
191
|
+
return init
|
|
192
192
|
|
|
193
193
|
|
|
194
194
|
def shutdown_mt5():
|
|
@@ -391,6 +391,7 @@ class Account(object):
|
|
|
391
391
|
password: Optional[str] = None,
|
|
392
392
|
server: Optional[str] = None,
|
|
393
393
|
timeout: Optional[int] = 60_000,
|
|
394
|
+
path: Optional[str] = None,
|
|
394
395
|
) -> Union[AccountInfo, None]:
|
|
395
396
|
"""
|
|
396
397
|
Get info on the current trading account or a specific account .
|
|
@@ -408,6 +409,8 @@ class Account(object):
|
|
|
408
409
|
If not specified, the value of 60 000 (60 seconds) is applied.
|
|
409
410
|
If the connection is not established within the specified time,
|
|
410
411
|
the call is forcibly terminated and the exception is generated.
|
|
412
|
+
path (str, optional): The path to the MetaTrader 5 terminal executable file.
|
|
413
|
+
Defaults to None (e.g., "C:/Program Files/MetaTrader 5/terminal64.exe").
|
|
411
414
|
|
|
412
415
|
Returns:
|
|
413
416
|
- AccountInfo in the form of a Namedtuple structure.
|
|
@@ -419,6 +422,15 @@ class Account(object):
|
|
|
419
422
|
# connect to the trade account specifying a password and a server
|
|
420
423
|
if account is not None and password is not None and server is not None:
|
|
421
424
|
try:
|
|
425
|
+
# If a path is provided, initialize the MT5 terminal with it
|
|
426
|
+
if path is not None:
|
|
427
|
+
check_mt5_connection(
|
|
428
|
+
path=path,
|
|
429
|
+
login=account,
|
|
430
|
+
password=password,
|
|
431
|
+
server=server,
|
|
432
|
+
timeout=timeout,
|
|
433
|
+
)
|
|
422
434
|
authorized = mt5.login(
|
|
423
435
|
account, password=password, server=server, timeout=timeout
|
|
424
436
|
)
|
|
@@ -760,10 +772,7 @@ class Account(object):
|
|
|
760
772
|
This mthods works primarly with Admirals Group AS products and Pepperstone Group Limited,
|
|
761
773
|
For other brokers use `get_symbols()` or this method will use it by default.
|
|
762
774
|
"""
|
|
763
|
-
if (
|
|
764
|
-
self.broker != AdmiralMarktsGroup()
|
|
765
|
-
or self.broker != PepperstoneGroupLimited()
|
|
766
|
-
):
|
|
775
|
+
if self.broker not in [AdmiralMarktsGroup(), PepperstoneGroupLimited()]:
|
|
767
776
|
return self.get_symbols(symbol_type=SymbolType.FOREX)
|
|
768
777
|
else:
|
|
769
778
|
fx_categories = {
|
|
@@ -816,11 +825,8 @@ class Account(object):
|
|
|
816
825
|
This mthods works primarly with Admirals Group AS products and Pepperstone Group Limited,
|
|
817
826
|
For other brokers use `get_symbols()` or this method will use it by default.
|
|
818
827
|
"""
|
|
819
|
-
|
|
820
|
-
if (
|
|
821
|
-
self.broker != AdmiralMarktsGroup()
|
|
822
|
-
or self.broker != PepperstoneGroupLimited()
|
|
823
|
-
):
|
|
828
|
+
|
|
829
|
+
if self.broker not in [AdmiralMarktsGroup(), PepperstoneGroupLimited()]:
|
|
824
830
|
return self.get_symbols(symbol_type=SymbolType.STOCKS)
|
|
825
831
|
else:
|
|
826
832
|
stocks, etfs = [], []
|
|
@@ -883,7 +889,7 @@ class Account(object):
|
|
|
883
889
|
SymbolType.STOCKS, exchange_code, exchange_map
|
|
884
890
|
)
|
|
885
891
|
etfs = self._get_symbols_by_category(
|
|
886
|
-
|
|
892
|
+
SymbolType.ETFs, exchange_code, exchange_map
|
|
887
893
|
)
|
|
888
894
|
return stocks + etfs if etf else stocks
|
|
889
895
|
|
|
@@ -1085,6 +1091,39 @@ class Account(object):
|
|
|
1085
1091
|
except Exception as e:
|
|
1086
1092
|
raise_mt5_error(e)
|
|
1087
1093
|
|
|
1094
|
+
def calculate_profit(
|
|
1095
|
+
self,
|
|
1096
|
+
action: Literal["buy", "sell"],
|
|
1097
|
+
symbol: str,
|
|
1098
|
+
lot: float,
|
|
1099
|
+
price_open: float,
|
|
1100
|
+
price_close: float,
|
|
1101
|
+
) -> float:
|
|
1102
|
+
"""
|
|
1103
|
+
Calculate profit in the account currency for a specified trading operation.
|
|
1104
|
+
|
|
1105
|
+
Args:
|
|
1106
|
+
action (str): The trading action, either 'buy' or 'sell'.
|
|
1107
|
+
symbol (str): The symbol of the financial instrument.
|
|
1108
|
+
lot (float): The lot size of the order.
|
|
1109
|
+
price_open (float): The price at which to position was opened.
|
|
1110
|
+
price_close (float): The price at which to position was closed.
|
|
1111
|
+
|
|
1112
|
+
Returns:
|
|
1113
|
+
float: The profit value
|
|
1114
|
+
|
|
1115
|
+
Raises:
|
|
1116
|
+
MT5TerminalError: A specific exception based on the error code.
|
|
1117
|
+
|
|
1118
|
+
"""
|
|
1119
|
+
actions = {"buy": mt5.ORDER_TYPE_BUY, "sell": mt5.ORDER_TYPE_SELL}
|
|
1120
|
+
try:
|
|
1121
|
+
return mt5.order_calc_profit(
|
|
1122
|
+
actions[action], symbol, lot, price_open, price_close
|
|
1123
|
+
)
|
|
1124
|
+
except Exception as e:
|
|
1125
|
+
raise_mt5_error(e)
|
|
1126
|
+
|
|
1088
1127
|
def check_order(self, request: Dict[str, Any]) -> OrderCheckResult:
|
|
1089
1128
|
"""
|
|
1090
1129
|
Check funds sufficiency for performing a required trading operation.
|
|
@@ -1533,3 +1572,29 @@ class Account(object):
|
|
|
1533
1572
|
else:
|
|
1534
1573
|
history_orders = [TradeOrder(**td._asdict()) for td in history_orders]
|
|
1535
1574
|
return tuple(history_orders)
|
|
1575
|
+
|
|
1576
|
+
def get_today_deals(self, id, group=None) -> List[TradeDeal]:
|
|
1577
|
+
"""
|
|
1578
|
+
Get all today deals for a specific symbol or group of symbols
|
|
1579
|
+
|
|
1580
|
+
Args:
|
|
1581
|
+
id (int): strategy or expert id
|
|
1582
|
+
group (str): Symbol or group or symbol
|
|
1583
|
+
Returns:
|
|
1584
|
+
List[TradeDeal]: List of today deals
|
|
1585
|
+
"""
|
|
1586
|
+
date_from = datetime.now() - timedelta(days=2)
|
|
1587
|
+
history = (
|
|
1588
|
+
self.get_trades_history(date_from=date_from, group=group, to_df=False) or []
|
|
1589
|
+
)
|
|
1590
|
+
positions_ids = set([deal.position_id for deal in history if deal.magic == id])
|
|
1591
|
+
today_deals = []
|
|
1592
|
+
for position in positions_ids:
|
|
1593
|
+
deal = self.get_trades_history(
|
|
1594
|
+
date_from=date_from, position=position, to_df=False
|
|
1595
|
+
)
|
|
1596
|
+
if deal is not None and len(deal) == 2:
|
|
1597
|
+
deal_time = datetime.fromtimestamp(deal[1].time)
|
|
1598
|
+
if deal_time.date() == datetime.now().date():
|
|
1599
|
+
today_deals.append(deal[1])
|
|
1600
|
+
return today_deals
|