bbstrader 0.2.91__py3-none-any.whl → 0.2.93__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/__main__.py +50 -0
- bbstrader/btengine/data.py +12 -9
- bbstrader/btengine/execution.py +13 -2
- bbstrader/btengine/performance.py +50 -1
- bbstrader/btengine/scripts.py +157 -0
- bbstrader/btengine/strategy.py +12 -2
- bbstrader/compat.py +2 -2
- bbstrader/config.py +2 -4
- bbstrader/core/utils.py +90 -1
- bbstrader/metatrader/__init__.py +2 -1
- bbstrader/metatrader/account.py +29 -39
- bbstrader/metatrader/copier.py +745 -0
- bbstrader/metatrader/rates.py +6 -3
- bbstrader/metatrader/risk.py +19 -8
- bbstrader/metatrader/scripts.py +81 -0
- bbstrader/metatrader/trade.py +178 -66
- bbstrader/metatrader/utils.py +5 -2
- bbstrader/models/ml.py +20 -12
- bbstrader/trading/execution.py +150 -33
- bbstrader/trading/script.py +155 -0
- bbstrader/trading/scripts.py +2 -0
- bbstrader/tseries.py +33 -7
- {bbstrader-0.2.91.dist-info → bbstrader-0.2.93.dist-info}/METADATA +6 -2
- bbstrader-0.2.93.dist-info/RECORD +44 -0
- {bbstrader-0.2.91.dist-info → bbstrader-0.2.93.dist-info}/WHEEL +1 -1
- bbstrader-0.2.93.dist-info/entry_points.txt +2 -0
- bbstrader-0.2.91.dist-info/RECORD +0 -38
- {bbstrader-0.2.91.dist-info → bbstrader-0.2.93.dist-info}/LICENSE +0 -0
- {bbstrader-0.2.91.dist-info → bbstrader-0.2.93.dist-info}/top_level.txt +0 -0
bbstrader/metatrader/account.py
CHANGED
|
@@ -4,8 +4,6 @@ import urllib.request
|
|
|
4
4
|
from datetime import datetime
|
|
5
5
|
from typing import Any, Dict, List, Literal, Optional, Tuple, Union
|
|
6
6
|
|
|
7
|
-
from bbstrader import compat # noqa: F401
|
|
8
|
-
import MetaTrader5 as mt5
|
|
9
7
|
import pandas as pd
|
|
10
8
|
from currency_converter import SINGLE_DAY_ECB_URL, CurrencyConverter
|
|
11
9
|
|
|
@@ -24,14 +22,19 @@ from bbstrader.metatrader.utils import (
|
|
|
24
22
|
raise_mt5_error,
|
|
25
23
|
)
|
|
26
24
|
|
|
25
|
+
try:
|
|
26
|
+
import MetaTrader5 as mt5
|
|
27
|
+
except ImportError:
|
|
28
|
+
import bbstrader.compat # noqa: F401
|
|
29
|
+
|
|
30
|
+
|
|
27
31
|
__all__ = [
|
|
28
32
|
"Account",
|
|
29
33
|
"Broker",
|
|
30
34
|
"AdmiralMarktsGroup",
|
|
31
35
|
"JustGlobalMarkets",
|
|
32
|
-
"TrinotaMarkets",
|
|
33
|
-
"XCubeLimited",
|
|
34
36
|
"PepperstoneGroupLimited",
|
|
37
|
+
"check_mt5_connection",
|
|
35
38
|
"FTMO",
|
|
36
39
|
]
|
|
37
40
|
|
|
@@ -39,8 +42,6 @@ __BROKERS__ = {
|
|
|
39
42
|
"AMG": "Admirals Group AS",
|
|
40
43
|
"JGM": "Just Global Markets Ltd.",
|
|
41
44
|
"FTMO": "FTMO S.R.O.",
|
|
42
|
-
"XCB": "4xCube Limited",
|
|
43
|
-
"TML": "Trinota Markets (Global) Limited",
|
|
44
45
|
"PGL": "Pepperstone Group Limited",
|
|
45
46
|
}
|
|
46
47
|
|
|
@@ -48,8 +49,6 @@ BROKERS_TIMEZONES = {
|
|
|
48
49
|
"AMG": "Europe/Helsinki",
|
|
49
50
|
"JGM": "Europe/Helsinki",
|
|
50
51
|
"FTMO": "Europe/Helsinki",
|
|
51
|
-
"XCB": "Europe/Helsinki",
|
|
52
|
-
"TML": "Europe/Helsinki",
|
|
53
52
|
"PGL": "Europe/Helsinki",
|
|
54
53
|
}
|
|
55
54
|
|
|
@@ -68,11 +67,11 @@ _ADMIRAL_MARKETS_PRODUCTS_ = [
|
|
|
68
67
|
]
|
|
69
68
|
_JUST_MARKETS_PRODUCTS_ = ["Stocks", "Crypto", "indices", "Commodities", "Forex"]
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
SUPPORTED_BROKERS = [__BROKERS__[b] for b in {"AMG", "JGM", "FTMO"}]
|
|
72
71
|
INIT_MSG = (
|
|
73
72
|
f"\n* Ensure you have a good and stable internet connexion\n"
|
|
74
73
|
f"* Ensure you have an activete MT5 terminal install on your machine\n"
|
|
75
|
-
f"* Ensure you have an active MT5 Account with {' or '.join(
|
|
74
|
+
f"* Ensure you have an active MT5 Account with {' or '.join(SUPPORTED_BROKERS)}\n"
|
|
76
75
|
f"* If you want to trade {', '.join(_ADMIRAL_MARKETS_PRODUCTS_)}, See [{_ADMIRAL_MARKETS_URL_}]\n"
|
|
77
76
|
f"* If you want to trade {', '.join(_JUST_MARKETS_PRODUCTS_)}, See [{_JUST_MARKETS_URL_}]\n"
|
|
78
77
|
f"* If you are looking for a prop firm, See [{_FTMO_URL_}]\n"
|
|
@@ -189,7 +188,10 @@ def check_mt5_connection(**kwargs):
|
|
|
189
188
|
except Exception:
|
|
190
189
|
raise_mt5_error(INIT_MSG)
|
|
191
190
|
|
|
192
|
-
|
|
191
|
+
def shutdown_mt5():
|
|
192
|
+
"""Close the connection to the MetaTrader 5 terminal."""
|
|
193
|
+
mt5.shutdown()
|
|
194
|
+
|
|
193
195
|
class Broker(object):
|
|
194
196
|
def __init__(self, name: str = None, **kwargs):
|
|
195
197
|
if name is None:
|
|
@@ -242,24 +244,6 @@ class FTMO(Broker):
|
|
|
242
244
|
return BROKERS_TIMEZONES["FTMO"]
|
|
243
245
|
|
|
244
246
|
|
|
245
|
-
class XCubeLimited(Broker):
|
|
246
|
-
def __init__(self, **kwargs):
|
|
247
|
-
super().__init__("4xCube Limited", **kwargs)
|
|
248
|
-
|
|
249
|
-
@property
|
|
250
|
-
def timezone(self) -> str:
|
|
251
|
-
return BROKERS_TIMEZONES["XCB"]
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
class TrinotaMarkets(Broker):
|
|
255
|
-
def __init__(self, **kwargs):
|
|
256
|
-
super().__init__("Trinota Markets (Global) Limited", **kwargs)
|
|
257
|
-
|
|
258
|
-
@property
|
|
259
|
-
def timezone(self) -> str:
|
|
260
|
-
return BROKERS_TIMEZONES["TML"]
|
|
261
|
-
|
|
262
|
-
|
|
263
247
|
class PepperstoneGroupLimited(Broker):
|
|
264
248
|
def __init__(self, **kwargs):
|
|
265
249
|
super().__init__("Pepperstone Group Limited", **kwargs)
|
|
@@ -276,8 +260,6 @@ BROKERS: Dict[str, Broker] = {
|
|
|
276
260
|
"FTMO": FTMO(),
|
|
277
261
|
"AMG": AdmiralMarktsGroup(),
|
|
278
262
|
"JGM": JustGlobalMarkets(),
|
|
279
|
-
"XCB": XCubeLimited(),
|
|
280
|
-
"TML": TrinotaMarkets(),
|
|
281
263
|
"PGL": PepperstoneGroupLimited(),
|
|
282
264
|
}
|
|
283
265
|
|
|
@@ -326,19 +308,25 @@ class Account(object):
|
|
|
326
308
|
|
|
327
309
|
"""
|
|
328
310
|
check_mt5_connection(**kwargs)
|
|
329
|
-
self._check_brokers()
|
|
311
|
+
self._check_brokers(**kwargs)
|
|
330
312
|
|
|
331
|
-
def _check_brokers(self):
|
|
313
|
+
def _check_brokers(self, **kwargs):
|
|
314
|
+
if kwargs.get("copy", False):
|
|
315
|
+
return
|
|
332
316
|
supported = BROKERS.copy()
|
|
333
317
|
if self.broker not in supported.values():
|
|
334
318
|
msg = (
|
|
335
319
|
f"{self.broker.name} is not currently supported broker for the Account() class\n"
|
|
336
|
-
f"Currently Supported brokers are: {', '.join(
|
|
320
|
+
f"Currently Supported brokers are: {', '.join(SUPPORTED_BROKERS)}\n"
|
|
337
321
|
f"For {supported['AMG'].name}, See [{amg_url}]\n"
|
|
338
322
|
f"For {supported['JGM'].name}, See [{jgm_url}]\n"
|
|
339
323
|
f"For {supported['FTMO'].name}, See [{ftmo_url}]\n"
|
|
340
324
|
)
|
|
341
325
|
raise InvalidBroker(message=msg)
|
|
326
|
+
|
|
327
|
+
def shutdown(self):
|
|
328
|
+
"""Close the connection to the MetaTrader 5 terminal."""
|
|
329
|
+
shutdown_mt5()
|
|
342
330
|
|
|
343
331
|
@property
|
|
344
332
|
def broker(self) -> Broker:
|
|
@@ -798,7 +786,9 @@ class Account(object):
|
|
|
798
786
|
}
|
|
799
787
|
return self._get_symbols_by_category("FX", category, fx_categories)
|
|
800
788
|
|
|
801
|
-
def get_stocks_from_country(
|
|
789
|
+
def get_stocks_from_country(
|
|
790
|
+
self, country_code: str = "USA", etf=False
|
|
791
|
+
) -> List[str]:
|
|
802
792
|
"""
|
|
803
793
|
Retrieves a list of stock symbols from a specific country.
|
|
804
794
|
|
|
@@ -970,7 +960,7 @@ class Account(object):
|
|
|
970
960
|
symbol (str): Symbol name
|
|
971
961
|
|
|
972
962
|
Returns:
|
|
973
|
-
-
|
|
963
|
+
- SymbolInfo in the form of a NamedTuple().
|
|
974
964
|
- None in case of an error.
|
|
975
965
|
|
|
976
966
|
Raises:
|
|
@@ -990,7 +980,7 @@ class Account(object):
|
|
|
990
980
|
return SymbolInfo(**symbol_info_dict)
|
|
991
981
|
except Exception as e:
|
|
992
982
|
msg = self._symbol_info_msg(symbol)
|
|
993
|
-
raise_mt5_error(message=f"{e+msg}")
|
|
983
|
+
raise_mt5_error(message=f"{e + msg}")
|
|
994
984
|
|
|
995
985
|
def show_symbol_info(self, symbol: str):
|
|
996
986
|
"""
|
|
@@ -1016,7 +1006,7 @@ class Account(object):
|
|
|
1016
1006
|
symbol (str): Symbol name
|
|
1017
1007
|
|
|
1018
1008
|
Returns:
|
|
1019
|
-
-
|
|
1009
|
+
- TickInfo in the form of a NamedTuple().
|
|
1020
1010
|
- None in case of an error.
|
|
1021
1011
|
|
|
1022
1012
|
Raises:
|
|
@@ -1036,7 +1026,7 @@ class Account(object):
|
|
|
1036
1026
|
return TickInfo(**info_dict)
|
|
1037
1027
|
except Exception as e:
|
|
1038
1028
|
msg = self._symbol_info_msg(symbol)
|
|
1039
|
-
raise_mt5_error(message=f"{e+msg}")
|
|
1029
|
+
raise_mt5_error(message=f"{e + msg}")
|
|
1040
1030
|
|
|
1041
1031
|
def show_tick_info(self, symbol: str):
|
|
1042
1032
|
"""
|