bbstrader 0.3.2__tar.gz → 0.3.3__tar.gz
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-0.3.2/bbstrader.egg-info → bbstrader-0.3.3}/PKG-INFO +2 -2
- {bbstrader-0.3.2 → bbstrader-0.3.3}/README.md +1 -1
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/__main__.py +5 -5
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/btengine/data.py +3 -3
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/btengine/strategy.py +9 -7
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/core/data.py +3 -1
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/core/scripts.py +62 -19
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/metatrader/account.py +32 -18
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/metatrader/copier.py +321 -171
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/metatrader/rates.py +2 -2
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/metatrader/utils.py +1 -5
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/models/nlp.py +16 -11
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/trading/execution.py +92 -41
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/tseries.py +0 -2
- {bbstrader-0.3.2 → bbstrader-0.3.3/bbstrader.egg-info}/PKG-INFO +2 -2
- {bbstrader-0.3.2 → bbstrader-0.3.3}/setup.py +1 -3
- {bbstrader-0.3.2 → bbstrader-0.3.3}/LICENSE +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/MANIFEST.in +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/__init__.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/btengine/__init__.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/btengine/backtest.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/btengine/event.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/btengine/execution.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/btengine/performance.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/btengine/portfolio.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/btengine/scripts.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/compat.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/config.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/core/__init__.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/core/utils.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/ibkr/__init__.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/ibkr/utils.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/metatrader/__init__.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/metatrader/analysis.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/metatrader/risk.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/metatrader/scripts.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/metatrader/trade.py +2 -2
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/models/__init__.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/models/factors.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/models/ml.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/models/optimization.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/models/portfolio.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/models/risk.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/trading/__init__.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/trading/scripts.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/trading/strategies.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader/trading/utils.py +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader.egg-info/SOURCES.txt +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader.egg-info/dependency_links.txt +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader.egg-info/entry_points.txt +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader.egg-info/requires.txt +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/bbstrader.egg-info/top_level.txt +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/requirements.txt +0 -0
- {bbstrader-0.3.2 → bbstrader-0.3.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bbstrader
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: Simplified Investment & Trading Toolkit
|
|
5
5
|
Home-page: https://github.com/bbalouki/bbstrader
|
|
6
6
|
Download-URL: https://pypi.org/project/bbstrader/
|
|
@@ -380,7 +380,7 @@ You may need to create the `~/.bbstrader/` directory and its subdirectories (lik
|
|
|
380
380
|
|
|
381
381
|
For comprehensive information, including detailed API references, tutorials, and advanced guides for each module, please refer to our full documentation hosted on ReadTheDocs:
|
|
382
382
|
|
|
383
|
-
[**View the Full Documentation
|
|
383
|
+
[**View the Full Documentation**](https://bbstrader.readthedocs.io/en/latest/)
|
|
384
384
|
|
|
385
385
|
Additionally, the codebase is commented and includes docstrings, which can be a valuable resource for understanding the implementation details of specific functions and classes.
|
|
386
386
|
|
|
@@ -301,7 +301,7 @@ You may need to create the `~/.bbstrader/` directory and its subdirectories (lik
|
|
|
301
301
|
|
|
302
302
|
For comprehensive information, including detailed API references, tutorials, and advanced guides for each module, please refer to our full documentation hosted on ReadTheDocs:
|
|
303
303
|
|
|
304
|
-
[**View the Full Documentation
|
|
304
|
+
[**View the Full Documentation**](https://bbstrader.readthedocs.io/en/latest/)
|
|
305
305
|
|
|
306
306
|
Additionally, the codebase is commented and includes docstrings, which can be a valuable resource for understanding the implementation details of specific functions and classes.
|
|
307
307
|
|
|
@@ -12,7 +12,7 @@ from bbstrader.metatrader.scripts import copy_trades
|
|
|
12
12
|
from bbstrader.trading.scripts import execute_strategy
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class
|
|
15
|
+
class _Module(Enum):
|
|
16
16
|
COPIER = "copier"
|
|
17
17
|
BACKTEST = "backtest"
|
|
18
18
|
EXECUTION = "execution"
|
|
@@ -52,13 +52,13 @@ def main():
|
|
|
52
52
|
sys.exit(0)
|
|
53
53
|
try:
|
|
54
54
|
match args.run:
|
|
55
|
-
case
|
|
55
|
+
case _Module.COPIER.value:
|
|
56
56
|
copy_trades(unknown)
|
|
57
|
-
case
|
|
57
|
+
case _Module.BACKTEST.value:
|
|
58
58
|
backtest(unknown)
|
|
59
|
-
case
|
|
59
|
+
case _Module.EXECUTION.value:
|
|
60
60
|
execute_strategy(unknown)
|
|
61
|
-
case
|
|
61
|
+
case _Module.NEWS_FEED.value:
|
|
62
62
|
send_news_feed(unknown)
|
|
63
63
|
case _:
|
|
64
64
|
print(Fore.RED + f"Unknown module: {args.run}")
|
|
@@ -361,7 +361,7 @@ class CSVDataHandler(BaseCSVDataHandler):
|
|
|
361
361
|
csv_dir (str): Absolute directory path to the CSV files.
|
|
362
362
|
|
|
363
363
|
NOTE:
|
|
364
|
-
All csv fille can be
|
|
364
|
+
All csv fille can be stored in 'Home/.bbstrader/data/csv_data'
|
|
365
365
|
|
|
366
366
|
"""
|
|
367
367
|
csv_dir = kwargs.get("csv_dir")
|
|
@@ -580,7 +580,7 @@ class EODHDataHandler(BaseCSVDataHandler):
|
|
|
580
580
|
to_unix_time=unix_end,
|
|
581
581
|
)
|
|
582
582
|
|
|
583
|
-
def
|
|
583
|
+
def _format_data(self, data: List[Dict] | pd.DataFrame) -> pd.DataFrame:
|
|
584
584
|
if isinstance(data, pd.DataFrame):
|
|
585
585
|
if data.empty or len(data) == 0:
|
|
586
586
|
raise ValueError("No data found.")
|
|
@@ -608,7 +608,7 @@ class EODHDataHandler(BaseCSVDataHandler):
|
|
|
608
608
|
filepath = os.path.join(cache_dir, f"{symbol}.csv")
|
|
609
609
|
try:
|
|
610
610
|
data = self._get_data(symbol, self.period)
|
|
611
|
-
data = self.
|
|
611
|
+
data = self._format_data(data)
|
|
612
612
|
data.to_csv(filepath)
|
|
613
613
|
except Exception as e:
|
|
614
614
|
raise ValueError(f"Error downloading {symbol}: {e}")
|
|
@@ -797,17 +797,19 @@ class MT5Strategy(Strategy):
|
|
|
797
797
|
return False
|
|
798
798
|
tick_info = self.account.get_tick_info(asset)
|
|
799
799
|
bid, ask = tick_info.bid, tick_info.ask
|
|
800
|
+
price = None
|
|
800
801
|
if len(prices) == 1:
|
|
801
802
|
price = prices[0]
|
|
802
803
|
elif len(prices) in range(2, self.max_trades[asset] + 1):
|
|
803
804
|
price = np.mean(prices)
|
|
804
|
-
if
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
805
|
+
if price is not None:
|
|
806
|
+
if (
|
|
807
|
+
position == 0
|
|
808
|
+
and self.calculate_pct_change(ask, price) >= th
|
|
809
|
+
or position == 1
|
|
810
|
+
and abs(self.calculate_pct_change(bid, price)) >= th
|
|
811
|
+
):
|
|
812
|
+
return True
|
|
811
813
|
return False
|
|
812
814
|
|
|
813
815
|
@staticmethod
|
|
@@ -190,7 +190,9 @@ class FmpNews(object):
|
|
|
190
190
|
0
|
|
191
191
|
] # if symbol is a yahoo finance ticker
|
|
192
192
|
source_methods = {
|
|
193
|
-
"articles": lambda: self.get_latest_articles(
|
|
193
|
+
"articles": lambda: self.get_latest_articles(
|
|
194
|
+
articles=articles, save=True, **kwargs
|
|
195
|
+
),
|
|
194
196
|
"releases": lambda: self.get_releases(symbol=symbol, **kwargs),
|
|
195
197
|
"stock": lambda: self.get_stock_news(symbol=symbol, **kwargs),
|
|
196
198
|
"crypto": lambda: self.get_crypto_news(symbol=symbol, **kwargs),
|
|
@@ -4,6 +4,7 @@ import sys
|
|
|
4
4
|
import textwrap
|
|
5
5
|
import time
|
|
6
6
|
from datetime import datetime, timedelta
|
|
7
|
+
from typing import List, Literal
|
|
7
8
|
|
|
8
9
|
import nltk
|
|
9
10
|
from loguru import logger
|
|
@@ -25,7 +26,7 @@ def summarize_text(text, sentences_count=5):
|
|
|
25
26
|
return " ".join(str(sentence) for sentence in summary)
|
|
26
27
|
|
|
27
28
|
|
|
28
|
-
def
|
|
29
|
+
def format_coindesk_article(article: dict) -> str:
|
|
29
30
|
if not all(
|
|
30
31
|
k in article
|
|
31
32
|
for k in (
|
|
@@ -53,16 +54,40 @@ def format_article_for_telegram(article: dict) -> str:
|
|
|
53
54
|
return text
|
|
54
55
|
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
def format_fmp_article(article: dict) -> str:
|
|
58
|
+
if not all(k in article for k in ("title", "date", "content", "tickers")):
|
|
59
|
+
return ""
|
|
60
|
+
summary = summarize_text(article["content"])
|
|
61
|
+
text = (
|
|
62
|
+
f"📰 {article['title']}\n"
|
|
63
|
+
f"Published Date: {article['date']}\n"
|
|
64
|
+
f"Keywords: {article['tickers']}\n\n"
|
|
65
|
+
f"🔍 Summary\n"
|
|
66
|
+
f"{textwrap.fill(summary, width=80)}"
|
|
67
|
+
)
|
|
68
|
+
return text
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
async def send_articles(
|
|
72
|
+
articles: List[dict],
|
|
73
|
+
token: str,
|
|
74
|
+
id: str,
|
|
75
|
+
source: Literal["coindesk", "fmp"],
|
|
76
|
+
interval=15,
|
|
77
|
+
):
|
|
57
78
|
for article in articles:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
79
|
+
message = ""
|
|
80
|
+
if source == "coindesk":
|
|
81
|
+
if article["published_on"] >= datetime.now() - timedelta(minutes=interval):
|
|
82
|
+
article["published_on"] = article.get("published_on").strftime(
|
|
83
|
+
"%Y-%m-%d %H:%M:%S"
|
|
84
|
+
)
|
|
85
|
+
message = format_coindesk_article(article)
|
|
86
|
+
else:
|
|
87
|
+
message = format_fmp_article(article)
|
|
88
|
+
if message == "":
|
|
89
|
+
return
|
|
90
|
+
await send_telegram_message(token, id, text=message)
|
|
66
91
|
|
|
67
92
|
|
|
68
93
|
def send_news_feed(unknown):
|
|
@@ -78,6 +103,7 @@ def send_news_feed(unknown):
|
|
|
78
103
|
-q, --query: The news to look for (default: "")
|
|
79
104
|
-t, --token: Telegram bot token
|
|
80
105
|
-I, --id: Telegram Chat id
|
|
106
|
+
--fmp: Financial Modeling Prop Api Key
|
|
81
107
|
-i, --interval: Interval in minutes to fetch news (default: 15)
|
|
82
108
|
|
|
83
109
|
Note:
|
|
@@ -101,6 +127,9 @@ def send_news_feed(unknown):
|
|
|
101
127
|
help="Telegram bot token",
|
|
102
128
|
)
|
|
103
129
|
parser.add_argument("-I", "--id", type=str, required=True, help="Telegram Chat id")
|
|
130
|
+
parser.add_argument(
|
|
131
|
+
"--fmp", type=str, default="", help="Financial Modeling Prop Api Key"
|
|
132
|
+
)
|
|
104
133
|
parser.add_argument(
|
|
105
134
|
"-i",
|
|
106
135
|
"--interval",
|
|
@@ -112,19 +141,33 @@ def send_news_feed(unknown):
|
|
|
112
141
|
|
|
113
142
|
nltk.download("punkt", quiet=True)
|
|
114
143
|
news = FinancialNews()
|
|
115
|
-
logger.info(
|
|
116
|
-
f"Starting the News Feed on {args.interval} minutes"
|
|
117
|
-
)
|
|
144
|
+
logger.info(f"Starting the News Feed on {args.interval} minutes")
|
|
118
145
|
while True:
|
|
119
146
|
try:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
147
|
+
fmp_articles = []
|
|
148
|
+
coindesk_articles = news.get_coindesk_news(query=args.query)
|
|
149
|
+
if args.fmp:
|
|
150
|
+
start = datetime.now() - timedelta(minutes=args.interval)
|
|
151
|
+
start = start.strftime("%Y-%m-%d %H:%M:%S")
|
|
152
|
+
end = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
153
|
+
fmp_articles = news.get_fmp_news(api=args.fmp).get_latest_articles(
|
|
154
|
+
save=True, start=start, end=end
|
|
155
|
+
)
|
|
156
|
+
if len(coindesk_articles) != 0:
|
|
157
|
+
asyncio.run(
|
|
158
|
+
send_articles(
|
|
159
|
+
coindesk_articles,
|
|
160
|
+
args.token,
|
|
161
|
+
args.id,
|
|
162
|
+
"coindesk",
|
|
163
|
+
interval=args.interval,
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
if len(fmp_articles) != 0:
|
|
167
|
+
asyncio.run(send_articles(fmp_articles, args.token, args.id, "fmp"))
|
|
125
168
|
time.sleep(args.interval * 60)
|
|
126
169
|
except KeyboardInterrupt:
|
|
127
170
|
logger.info("Stopping the News Feed ...")
|
|
128
|
-
exit(0)
|
|
171
|
+
sys.exit(0)
|
|
129
172
|
except Exception as e:
|
|
130
173
|
logger.error(e)
|
|
@@ -5,8 +5,6 @@ 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
|
|
8
|
-
from currency_converter import SINGLE_DAY_ECB_URL, CurrencyConverter
|
|
9
|
-
|
|
10
8
|
from bbstrader.metatrader.utils import (
|
|
11
9
|
AccountInfo,
|
|
12
10
|
BookInfo,
|
|
@@ -23,6 +21,7 @@ from bbstrader.metatrader.utils import (
|
|
|
23
21
|
TradeRequest,
|
|
24
22
|
raise_mt5_error,
|
|
25
23
|
)
|
|
24
|
+
from currency_converter import SINGLE_DAY_ECB_URL, CurrencyConverter
|
|
26
25
|
|
|
27
26
|
try:
|
|
28
27
|
import MetaTrader5 as mt5
|
|
@@ -33,6 +32,7 @@ except ImportError:
|
|
|
33
32
|
__all__ = [
|
|
34
33
|
"Account",
|
|
35
34
|
"Broker",
|
|
35
|
+
"MetaQuotes",
|
|
36
36
|
"AdmiralMarktsGroup",
|
|
37
37
|
"JustGlobalMarkets",
|
|
38
38
|
"PepperstoneGroupLimited",
|
|
@@ -41,6 +41,7 @@ __all__ = [
|
|
|
41
41
|
]
|
|
42
42
|
|
|
43
43
|
__BROKERS__ = {
|
|
44
|
+
"MQL": "MetaQuotes Ltd.",
|
|
44
45
|
"AMG": "Admirals Group AS",
|
|
45
46
|
"JGM": "Just Global Markets Ltd.",
|
|
46
47
|
"FTMO": "FTMO S.R.O.",
|
|
@@ -67,14 +68,13 @@ _ADMIRAL_MARKETS_PRODUCTS_ = [
|
|
|
67
68
|
]
|
|
68
69
|
_JUST_MARKETS_PRODUCTS_ = ["Stocks", "Crypto", "indices", "Commodities", "Forex"]
|
|
69
70
|
|
|
70
|
-
SUPPORTED_BROKERS = [__BROKERS__[b] for b in {"AMG", "JGM", "FTMO"}]
|
|
71
|
+
SUPPORTED_BROKERS = [__BROKERS__[b] for b in {"MQL", "AMG", "JGM", "FTMO"}]
|
|
71
72
|
INIT_MSG = (
|
|
72
|
-
f"\n*
|
|
73
|
-
f"*
|
|
74
|
-
f"*
|
|
75
|
-
f"
|
|
76
|
-
f"*
|
|
77
|
-
f"* If you are looking for a prop firm, See [{_FTMO_URL_}]\n"
|
|
73
|
+
f"\n* Check your internet connection\n"
|
|
74
|
+
f"* Make sure MT5 is installed and active\n"
|
|
75
|
+
f"* Looking for a boker? See [{_ADMIRAL_MARKETS_URL_}] "
|
|
76
|
+
f"or [{_JUST_MARKETS_URL_}]\n"
|
|
77
|
+
f"* Looking for a prop firm? See [{_FTMO_URL_}]\n"
|
|
78
78
|
)
|
|
79
79
|
|
|
80
80
|
amg_url = _ADMIRAL_MARKETS_URL_
|
|
@@ -136,7 +136,16 @@ AMG_EXCHANGES = {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
|
|
139
|
-
def check_mt5_connection(
|
|
139
|
+
def check_mt5_connection(
|
|
140
|
+
*,
|
|
141
|
+
path=None,
|
|
142
|
+
login=None,
|
|
143
|
+
password=None,
|
|
144
|
+
server=None,
|
|
145
|
+
timeout=60_000,
|
|
146
|
+
portable=False,
|
|
147
|
+
**kwargs,
|
|
148
|
+
) -> bool:
|
|
140
149
|
"""
|
|
141
150
|
Initialize the connection to the MetaTrader 5 terminal.
|
|
142
151
|
|
|
@@ -156,13 +165,12 @@ def check_mt5_connection(**kwargs) -> bool:
|
|
|
156
165
|
- Follow these instructions to lunch each terminal in portable mode first:
|
|
157
166
|
https://www.metatrader5.com/en/terminal/help/start_advanced/start#configuration_file
|
|
158
167
|
"""
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
168
|
+
if login is not None and server is not None:
|
|
169
|
+
account_info = mt5.account_info()
|
|
170
|
+
if account_info is not None:
|
|
171
|
+
if account_info.login == login and account_info.server == server:
|
|
172
|
+
return True
|
|
173
|
+
|
|
166
174
|
init = False
|
|
167
175
|
if path is None and (login or password or server):
|
|
168
176
|
raise ValueError(
|
|
@@ -221,6 +229,11 @@ class Broker(object):
|
|
|
221
229
|
return f"{self.__class__.__name__}({self.name})"
|
|
222
230
|
|
|
223
231
|
|
|
232
|
+
class MetaQuotes(Broker):
|
|
233
|
+
def __init__(self, **kwargs):
|
|
234
|
+
super().__init__(__BROKERS__["MQL"], **kwargs)
|
|
235
|
+
|
|
236
|
+
|
|
224
237
|
class AdmiralMarktsGroup(Broker):
|
|
225
238
|
def __init__(self, **kwargs):
|
|
226
239
|
super().__init__(__BROKERS__["AMG"], **kwargs)
|
|
@@ -262,6 +275,7 @@ class AMP(Broker): ...
|
|
|
262
275
|
|
|
263
276
|
BROKERS: Dict[str, Broker] = {
|
|
264
277
|
"FTMO": FTMO(),
|
|
278
|
+
"MQL": MetaQuotes(),
|
|
265
279
|
"AMG": AdmiralMarktsGroup(),
|
|
266
280
|
"JGM": JustGlobalMarkets(),
|
|
267
281
|
"PGL": PepperstoneGroupLimited(),
|
|
@@ -1372,7 +1386,7 @@ class Account(object):
|
|
|
1372
1386
|
group: Optional[str] = None,
|
|
1373
1387
|
ticket: Optional[int] = None,
|
|
1374
1388
|
to_df: bool = False,
|
|
1375
|
-
) -> Union[pd.DataFrame, Tuple[TradeOrder]
|
|
1389
|
+
) -> Union[pd.DataFrame, Tuple[TradeOrder]]:
|
|
1376
1390
|
"""
|
|
1377
1391
|
Get active orders with the ability to filter by symbol or ticket.
|
|
1378
1392
|
There are four call options:
|