bbstrader 0.2.95__py3-none-any.whl → 0.2.97__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 +3 -2
- bbstrader/btengine/data.py +6 -6
- bbstrader/btengine/execution.py +1 -1
- bbstrader/btengine/strategy.py +87 -99
- bbstrader/core/__init__.py +2 -0
- bbstrader/core/data.py +424 -7
- bbstrader/core/utils.py +2 -58
- bbstrader/metatrader/copier.py +1 -0
- bbstrader/metatrader/trade.py +157 -11
- bbstrader/models/__init__.py +1 -0
- bbstrader/models/ml.py +7 -7
- bbstrader/models/nlp.py +784 -0
- bbstrader/models/risk.py +2 -2
- bbstrader/trading/execution.py +18 -7
- bbstrader/trading/scripts.py +144 -58
- bbstrader/trading/strategies.py +6 -0
- bbstrader/trading/utils.py +69 -0
- {bbstrader-0.2.95.dist-info → bbstrader-0.2.97.dist-info}/METADATA +11 -2
- {bbstrader-0.2.95.dist-info → bbstrader-0.2.97.dist-info}/RECORD +23 -22
- {bbstrader-0.2.95.dist-info → bbstrader-0.2.97.dist-info}/WHEEL +1 -1
- bbstrader/trading/script.py +0 -155
- {bbstrader-0.2.95.dist-info → bbstrader-0.2.97.dist-info}/entry_points.txt +0 -0
- {bbstrader-0.2.95.dist-info → bbstrader-0.2.97.dist-info/licenses}/LICENSE +0 -0
- {bbstrader-0.2.95.dist-info → bbstrader-0.2.97.dist-info}/top_level.txt +0 -0
bbstrader/models/risk.py
CHANGED
|
@@ -68,7 +68,7 @@ class RiskModel(metaclass=ABCMeta):
|
|
|
68
68
|
such as historical returns or volatility, used to
|
|
69
69
|
assess market conditions.
|
|
70
70
|
"""
|
|
71
|
-
|
|
71
|
+
pass
|
|
72
72
|
|
|
73
73
|
@abstractmethod
|
|
74
74
|
def which_quantity_allowed(self):
|
|
@@ -76,7 +76,7 @@ class RiskModel(metaclass=ABCMeta):
|
|
|
76
76
|
Defines the strategy for asset allocation within
|
|
77
77
|
the portfolio to optimize risk-reward ratio.
|
|
78
78
|
"""
|
|
79
|
-
|
|
79
|
+
pass
|
|
80
80
|
|
|
81
81
|
|
|
82
82
|
class HMMRiskManager(RiskModel):
|
bbstrader/trading/execution.py
CHANGED
|
@@ -8,10 +8,9 @@ from loguru import logger as log
|
|
|
8
8
|
|
|
9
9
|
from bbstrader.btengine.strategy import MT5Strategy, Strategy
|
|
10
10
|
from bbstrader.config import BBSTRADER_DIR
|
|
11
|
-
from bbstrader.core.utils import TradeAction
|
|
12
11
|
from bbstrader.metatrader.account import Account, check_mt5_connection
|
|
13
|
-
from bbstrader.metatrader.trade import Trade
|
|
14
|
-
from bbstrader.trading.
|
|
12
|
+
from bbstrader.metatrader.trade import Trade, TradeAction
|
|
13
|
+
from bbstrader.trading.utils import send_message
|
|
15
14
|
|
|
16
15
|
try:
|
|
17
16
|
import MetaTrader5 as MT5
|
|
@@ -114,6 +113,7 @@ def _mt5_execution(
|
|
|
114
113
|
comment,
|
|
115
114
|
**kwargs,
|
|
116
115
|
):
|
|
116
|
+
global logger
|
|
117
117
|
logger = kwargs.get("logger", log)
|
|
118
118
|
|
|
119
119
|
def _print_exc(dm, msg):
|
|
@@ -168,6 +168,7 @@ def _mt5_execution(
|
|
|
168
168
|
if symbol not in weights:
|
|
169
169
|
continue
|
|
170
170
|
trade = trades_instances[symbol]
|
|
171
|
+
assert daily_risk is not None
|
|
171
172
|
dailydd = round(weights[symbol] * daily_risk, 5)
|
|
172
173
|
trade.dailydd = dailydd
|
|
173
174
|
|
|
@@ -212,7 +213,9 @@ def _mt5_execution(
|
|
|
212
213
|
f"Running {STRATEGY} Strategy in {time_frame} Interval ..., ACCOUNT={ACCOUNT}"
|
|
213
214
|
)
|
|
214
215
|
|
|
215
|
-
def run_trade_algorithm(
|
|
216
|
+
def run_trade_algorithm(
|
|
217
|
+
signal, symbol, id, trade: Trade, price, stoplimit, comment
|
|
218
|
+
):
|
|
216
219
|
signal = "BMKT" if signal == "LONG" or signal == "BUY" else signal
|
|
217
220
|
signal = "SMKT" if signal == "SHORT" or signal == "SELL" else signal
|
|
218
221
|
info = f"SIGNAL = {signal}, SYMBOL={symbol}, STRATEGY={STRATEGY}, TIMEFRAME={time_frame} , ACCOUNT={ACCOUNT}"
|
|
@@ -242,9 +245,13 @@ def _mt5_execution(
|
|
|
242
245
|
if notify:
|
|
243
246
|
_send_notification(sigmsg, symbol)
|
|
244
247
|
if position_type in POSITIONS_TYPES:
|
|
245
|
-
trade.close_positions(
|
|
248
|
+
trade.close_positions(
|
|
249
|
+
position_type=order_type, id=id, comment=comment
|
|
250
|
+
)
|
|
246
251
|
else:
|
|
247
|
-
trade.close_orders(
|
|
252
|
+
trade.close_orders(
|
|
253
|
+
order_type=order_type, id=id, comment=comment
|
|
254
|
+
)
|
|
248
255
|
elif signal in BUYS and not long_market[symbol]:
|
|
249
256
|
if use_trade_time:
|
|
250
257
|
if time_intervals % trade_time == 0 or buys[symbol] is None:
|
|
@@ -412,6 +419,7 @@ def _mt5_execution(
|
|
|
412
419
|
trade,
|
|
413
420
|
signal.price,
|
|
414
421
|
signal.stoplimit,
|
|
422
|
+
signal.comment or comment,
|
|
415
423
|
)
|
|
416
424
|
else:
|
|
417
425
|
if len(symbols) >= 10:
|
|
@@ -592,6 +600,9 @@ def _mt5_execution(
|
|
|
592
600
|
)
|
|
593
601
|
_print_exc(debug_mode, msg)
|
|
594
602
|
continue
|
|
603
|
+
except KeyboardInterrupt:
|
|
604
|
+
logger.info("Stopping the Execution Engine ...")
|
|
605
|
+
break
|
|
595
606
|
|
|
596
607
|
|
|
597
608
|
def _tws_execution(*args, **kwargs):
|
|
@@ -819,7 +830,7 @@ def mt5_engine(account_id: str, **kwargs):
|
|
|
819
830
|
|
|
820
831
|
def RunMt5Engines(accounts: Dict[str, Dict], start_delay: float = 1.0):
|
|
821
832
|
"""Runs multiple MT5 execution engines in parallel using multiprocessing.
|
|
822
|
-
|
|
833
|
+
|
|
823
834
|
Args:
|
|
824
835
|
accounts: Dictionary of accounts to run the execution engines on.
|
|
825
836
|
Keys are the account names or IDs and values are the parameters for the execution engine.
|
bbstrader/trading/scripts.py
CHANGED
|
@@ -1,69 +1,155 @@
|
|
|
1
|
-
import
|
|
1
|
+
import argparse
|
|
2
|
+
import json
|
|
3
|
+
import multiprocessing as mp
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
2
6
|
|
|
3
|
-
from
|
|
4
|
-
from
|
|
5
|
-
from
|
|
7
|
+
from bbstrader.btengine import MT5Strategy, Strategy
|
|
8
|
+
from bbstrader.core.utils import load_class, load_module
|
|
9
|
+
from bbstrader.metatrader.trade import create_trade_instance
|
|
10
|
+
from bbstrader.trading.execution import mt5_engine
|
|
6
11
|
|
|
12
|
+
EXECUTION_PATH = os.path.expanduser("~/.bbstrader/execution/execution.py")
|
|
13
|
+
CONFIG_PATH = os.path.expanduser("~/.bbstrader/execution/execution.json")
|
|
7
14
|
|
|
8
|
-
__all__ = ["send_telegram_message", "send_notification", "send_message"]
|
|
9
15
|
|
|
16
|
+
def load_config(config_path, strategy_name, account=None):
|
|
17
|
+
if not os.path.exists(config_path):
|
|
18
|
+
raise FileNotFoundError(f"Configuration file not found at {config_path}")
|
|
19
|
+
with open(config_path, "r") as f:
|
|
20
|
+
config = json.load(f)
|
|
21
|
+
try:
|
|
22
|
+
config = config[strategy_name]
|
|
23
|
+
except KeyError:
|
|
24
|
+
raise ValueError(
|
|
25
|
+
f"Strategy {strategy_name} not found in the configuration file."
|
|
26
|
+
)
|
|
27
|
+
if account is not None:
|
|
28
|
+
try:
|
|
29
|
+
config = config[account]
|
|
30
|
+
except KeyError:
|
|
31
|
+
raise ValueError(f"Account {account} not found in the configuration file.")
|
|
32
|
+
if config.get("symbol_list") is None:
|
|
33
|
+
raise ValueError("symbol_list is required in the configuration file.")
|
|
34
|
+
if config.get("trades_kwargs") is None:
|
|
35
|
+
raise ValueError("trades_kwargs is required in the configuration file.")
|
|
36
|
+
return config
|
|
10
37
|
|
|
11
|
-
async def send_telegram_message(token, chat_id, text=""):
|
|
12
|
-
"""
|
|
13
|
-
Send a message to a telegram chat
|
|
14
38
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
text: str: Message to send
|
|
19
|
-
"""
|
|
20
|
-
try:
|
|
21
|
-
bot = Bot(token=token)
|
|
22
|
-
if isinstance(chat_id, (int, str)):
|
|
23
|
-
chat_id = [chat_id]
|
|
24
|
-
for id in chat_id:
|
|
25
|
-
await bot.send_message(chat_id=id, text=text)
|
|
26
|
-
except TelegramError as e:
|
|
27
|
-
print(f"Error sending message: {e}")
|
|
39
|
+
def worker_function(account, args):
|
|
40
|
+
strategy_module = load_module(args.path)
|
|
41
|
+
strategy_class = load_class(strategy_module, args.strategy, (MT5Strategy, Strategy))
|
|
28
42
|
|
|
43
|
+
config = load_config(args.config, args.strategy, account)
|
|
44
|
+
symbol_list = config.pop("symbol_list")
|
|
45
|
+
trades_kwargs = config.pop("trades_kwargs")
|
|
46
|
+
trades = create_trade_instance(symbol_list, trades_kwargs)
|
|
29
47
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
48
|
+
kwargs = {
|
|
49
|
+
"symbol_list": symbol_list,
|
|
50
|
+
"trades_instances": trades,
|
|
51
|
+
"strategy_cls": strategy_class,
|
|
52
|
+
"account": account,
|
|
53
|
+
**config,
|
|
54
|
+
}
|
|
55
|
+
mt5_engine(account, **kwargs)
|
|
33
56
|
|
|
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
|
-
|
|
57
|
+
|
|
58
|
+
def mt5_terminal(args):
|
|
59
|
+
if args.parallel:
|
|
60
|
+
if len(args.account) == 0:
|
|
61
|
+
raise ValueError(
|
|
62
|
+
"account or accounts are required when running in parallel"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
processes = []
|
|
66
|
+
try:
|
|
67
|
+
for account in args.account:
|
|
68
|
+
p = mp.Process(target=worker_function, args=(account, args))
|
|
69
|
+
p.start()
|
|
70
|
+
processes.append(p)
|
|
71
|
+
|
|
72
|
+
for p in processes:
|
|
73
|
+
p.join()
|
|
74
|
+
except Exception as e:
|
|
75
|
+
print(f"Error in parallel execution: {e}")
|
|
76
|
+
raise e
|
|
77
|
+
except KeyboardInterrupt:
|
|
78
|
+
print("\nTerminating Execution...")
|
|
79
|
+
for p in processes:
|
|
80
|
+
p.terminate()
|
|
81
|
+
for p in processes:
|
|
82
|
+
p.join()
|
|
83
|
+
print("Execution terminated")
|
|
84
|
+
else:
|
|
85
|
+
worker_function(None, args)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def tws_terminal(args):
|
|
89
|
+
raise NotImplementedError("TWS terminal is not implemented yet")
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def execute_strategy(unknown):
|
|
93
|
+
HELP_MSG = """
|
|
94
|
+
Execute a strategy on one or multiple MT5 accounts.
|
|
95
|
+
|
|
96
|
+
Usage:
|
|
97
|
+
python -m bbstrader --run execution [options]
|
|
98
|
+
|
|
99
|
+
Options:
|
|
100
|
+
-s, --strategy: Strategy class name to run
|
|
101
|
+
-a, --account: Account(s) name(s) or ID(s) to run the strategy on (must be the same as in the configuration file)
|
|
102
|
+
-p, --path: Path to the execution file (default: ~/.bbstrader/execution/execution.py)
|
|
103
|
+
-c, --config: Path to the configuration file (default: ~/.bbstrader/execution/execution.json)
|
|
104
|
+
-l, --parallel: Run the strategy in parallel (default: False)
|
|
105
|
+
-t, --terminal: Terminal to use (default: MT5)
|
|
106
|
+
-h, --help: Show this help message and exit
|
|
107
|
+
|
|
108
|
+
Note:
|
|
109
|
+
The configuration file must contain all the required parameters
|
|
110
|
+
to create trade instances for each account and strategy.
|
|
111
|
+
The configuration file must be a dictionary with the following structure:
|
|
112
|
+
If parallel is True:
|
|
113
|
+
{
|
|
114
|
+
"strategy_name": {
|
|
115
|
+
"account_name": {
|
|
116
|
+
"symbol_list": ["symbol1", "symbol2"],
|
|
117
|
+
"trades_kwargs": {"param1": "value1", "param2": "value2"}
|
|
118
|
+
**other_parameters (for the strategy and the execution engine)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
If parallel is False:
|
|
123
|
+
{
|
|
124
|
+
"strategy_name": {
|
|
125
|
+
"symbol_list": ["symbol1", "symbol2"],
|
|
126
|
+
"trades_kwargs": {"param1": "value1", "param2": "value2"}
|
|
127
|
+
**other_parameters (for the strategy and the execution engine)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
See bbstrader.metatrader.trade.create_trade_instance for more details on the trades_kwargs.
|
|
131
|
+
See bbstrader.trading.execution.MT5ExecutionEngine for more details on the other parameters.
|
|
132
|
+
|
|
133
|
+
All other paramaters must be python built-in types.
|
|
134
|
+
If you have custom type you must set them in your strategy class
|
|
135
|
+
or run the MT5ExecutionEngine directly, don't run on CLI.
|
|
62
136
|
"""
|
|
63
|
-
if
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
137
|
+
if "-h" in unknown or "--help" in unknown:
|
|
138
|
+
print(HELP_MSG)
|
|
139
|
+
sys.exit(0)
|
|
140
|
+
|
|
141
|
+
parser = argparse.ArgumentParser()
|
|
142
|
+
parser.add_argument("-s", "--strategy", type=str, required=True)
|
|
143
|
+
parser.add_argument("-a", "--account", type=str, nargs="*", default=[])
|
|
144
|
+
parser.add_argument("-p", "--path", type=str, default=EXECUTION_PATH)
|
|
145
|
+
parser.add_argument("-c", "--config", type=str, default=CONFIG_PATH)
|
|
146
|
+
parser.add_argument("-l", "--parallel", action="store_true")
|
|
147
|
+
parser.add_argument(
|
|
148
|
+
"-t", "--terminal", type=str, default="MT5", choices=["MT5", "TWS"]
|
|
149
|
+
)
|
|
150
|
+
args = parser.parse_args(unknown)
|
|
69
151
|
|
|
152
|
+
if args.terminal == "MT5":
|
|
153
|
+
mt5_terminal(args)
|
|
154
|
+
elif args.terminal == "TWS":
|
|
155
|
+
tws_terminal(args)
|
bbstrader/trading/strategies.py
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Strategies module for trading strategies backtesting and execution.
|
|
3
|
+
|
|
4
|
+
DISCLAIMER:
|
|
5
|
+
This module is for educational purposes only and should not be
|
|
6
|
+
considered as financial advice. Always consult with a qualified financial advisor before making any investment decisions.
|
|
7
|
+
The authors and contributors of this module are not responsible for any financial losses or damages incurred as a result of using
|
|
8
|
+
this module or the information contained herein.
|
|
3
9
|
"""
|
|
4
10
|
|
|
5
11
|
from datetime import datetime
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
from notifypy import Notify
|
|
4
|
+
from telegram import Bot
|
|
5
|
+
from telegram.error import TelegramError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
__all__ = ["send_telegram_message", "send_notification", "send_message"]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
async def send_telegram_message(token, chat_id, text=""):
|
|
12
|
+
"""
|
|
13
|
+
Send a message to a telegram chat
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
token: str: Telegram bot token
|
|
17
|
+
chat_id: int or str or list: Chat id or list of chat ids
|
|
18
|
+
text: str: Message to send
|
|
19
|
+
"""
|
|
20
|
+
try:
|
|
21
|
+
bot = Bot(token=token)
|
|
22
|
+
if isinstance(chat_id, (int, str)):
|
|
23
|
+
chat_id = [chat_id]
|
|
24
|
+
for id in chat_id:
|
|
25
|
+
await bot.send_message(chat_id=id, text=text)
|
|
26
|
+
except TelegramError as e:
|
|
27
|
+
print(f"Error sending message: {e}")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def send_notification(title, message=""):
|
|
31
|
+
"""
|
|
32
|
+
Send a desktop notification
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
title: str: Title of the notification
|
|
36
|
+
message: str: Message of the notification
|
|
37
|
+
"""
|
|
38
|
+
notification = Notify(default_notification_application_name="bbstrading")
|
|
39
|
+
notification.title = title
|
|
40
|
+
notification.message = message
|
|
41
|
+
notification.send()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def send_message(
|
|
45
|
+
title="SIGNAL",
|
|
46
|
+
message="New signal",
|
|
47
|
+
notify_me=False,
|
|
48
|
+
telegram=False,
|
|
49
|
+
token=None,
|
|
50
|
+
chat_id=None,
|
|
51
|
+
):
|
|
52
|
+
"""
|
|
53
|
+
Send a message to the user
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
title: str: Title of the message
|
|
57
|
+
message: str: Message of the message
|
|
58
|
+
notify_me: bool: Send a desktop notification
|
|
59
|
+
telegram: bool: Send a telegram message
|
|
60
|
+
token: str: Telegram bot token
|
|
61
|
+
chat_id: int or str or list: Chat id or list of chat ids
|
|
62
|
+
"""
|
|
63
|
+
if notify_me:
|
|
64
|
+
send_notification(title, message=message)
|
|
65
|
+
if telegram:
|
|
66
|
+
if token is None or chat_id is None:
|
|
67
|
+
raise ValueError("Token and chat_id must be provided")
|
|
68
|
+
asyncio.run(send_telegram_message(token, chat_id, text=message))
|
|
69
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: bbstrader
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.97
|
|
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/
|
|
@@ -58,6 +58,14 @@ Requires-Dist: lightgbm
|
|
|
58
58
|
Requires-Dist: alphalens-reloaded
|
|
59
59
|
Requires-Dist: pyfiglet
|
|
60
60
|
Requires-Dist: colorama
|
|
61
|
+
Requires-Dist: praw
|
|
62
|
+
Requires-Dist: tweepy
|
|
63
|
+
Requires-Dist: beautifulsoup4
|
|
64
|
+
Requires-Dist: dash
|
|
65
|
+
Requires-Dist: nltk
|
|
66
|
+
Requires-Dist: spacy
|
|
67
|
+
Requires-Dist: textblob
|
|
68
|
+
Requires-Dist: vaderSentiment
|
|
61
69
|
Provides-Extra: mt5
|
|
62
70
|
Requires-Dist: MetaTrader5; extra == "mt5"
|
|
63
71
|
Dynamic: author
|
|
@@ -69,6 +77,7 @@ Dynamic: download-url
|
|
|
69
77
|
Dynamic: home-page
|
|
70
78
|
Dynamic: keywords
|
|
71
79
|
Dynamic: license
|
|
80
|
+
Dynamic: license-file
|
|
72
81
|
Dynamic: maintainer
|
|
73
82
|
Dynamic: project-url
|
|
74
83
|
Dynamic: provides-extra
|
|
@@ -1,44 +1,45 @@
|
|
|
1
1
|
bbstrader/__ini__.py,sha256=v6zyJHj5FMRL-_P7AwnTGbCF-riMqhqlTvDgfulj7go,621
|
|
2
|
-
bbstrader/__main__.py,sha256=
|
|
2
|
+
bbstrader/__main__.py,sha256=EtfD-TrAphboYxwfe7-WeD-1d4bJceeBputFrV-W-qQ,1525
|
|
3
3
|
bbstrader/compat.py,sha256=djbHMvTvy0HYm1zyZ6Ttp_LMwP2PqTSVw1r7pqbz7So,487
|
|
4
4
|
bbstrader/config.py,sha256=c2nCUw-bYWf5kkyFls5Nqld8HdMczexSilTni7rYUBw,3973
|
|
5
5
|
bbstrader/tseries.py,sha256=H4D_A966HdN8YjBfuCcF8QBQdhjOrTcidR98wP2KN_I,68339
|
|
6
6
|
bbstrader/btengine/__init__.py,sha256=y1btjaEfhWsH8vuE7mBRpP9Tu-Azt9REhuVYsPCAfBU,2955
|
|
7
7
|
bbstrader/btengine/backtest.py,sha256=ZzGhoN-_g0cF-OCyk173imze2OXEhykHTUiJ9MowDO8,14582
|
|
8
|
-
bbstrader/btengine/data.py,sha256=
|
|
8
|
+
bbstrader/btengine/data.py,sha256=Tuc6M8itbGpPjsfRpZBB8v0FJpPt7-hUkP6I5meP0Sg,26927
|
|
9
9
|
bbstrader/btengine/event.py,sha256=38mhZH9d53C4x7bZER2B0O6M18txzS4u7zveKyxeP5Y,8603
|
|
10
|
-
bbstrader/btengine/execution.py,sha256=
|
|
10
|
+
bbstrader/btengine/execution.py,sha256=mXY0tyFv6G1XF48R5Kx2-pDnwu1mUyOc0ZeeysQG62A,10587
|
|
11
11
|
bbstrader/btengine/performance.py,sha256=1ecWrTzHBQbk4ORvbTEKxwCzlL1brcXOEUwgbnjAwx4,12470
|
|
12
12
|
bbstrader/btengine/portfolio.py,sha256=mh2_zNJDmKzb0lo55PXhbXYxXMmXRA4YLkgzwxRMuZE,16110
|
|
13
13
|
bbstrader/btengine/scripts.py,sha256=8o66dq4Ex4DsH4s8xvJqUOFjLzZJSnbBvvNBzohtzoE,4837
|
|
14
|
-
bbstrader/btengine/strategy.py,sha256=
|
|
15
|
-
bbstrader/core/__init__.py,sha256=
|
|
16
|
-
bbstrader/core/data.py,sha256=
|
|
17
|
-
bbstrader/core/utils.py,sha256=
|
|
14
|
+
bbstrader/btengine/strategy.py,sha256=PFIb9gUWahaXpzCFL-RchpBumlEJsz5Elbz_A2qZ8Jc,31285
|
|
15
|
+
bbstrader/core/__init__.py,sha256=GIFzFSStPfE0XM2j7mDeZZQeMTh_AwPsDOQXwMVJLgw,97
|
|
16
|
+
bbstrader/core/data.py,sha256=VPuynoT0uFYduh7la8gZSnEv_Gq8Xu2vJZJ7TfQMll8,18797
|
|
17
|
+
bbstrader/core/utils.py,sha256=WjuabzBjhY65ku2KL-f7CMalE2x-wrX-6mCA_qhhFPE,2728
|
|
18
18
|
bbstrader/ibkr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
19
19
|
bbstrader/ibkr/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
20
|
bbstrader/metatrader/__init__.py,sha256=A5Ye9tpc2sp9Xk5qjKw-EfYsoRcZtAt8nqvC3tCtZs8,333
|
|
21
21
|
bbstrader/metatrader/account.py,sha256=qAFqCPmoUjiqjY5M9sjbSvh-STjQUGdFCHOEcB7uoDI,56493
|
|
22
|
-
bbstrader/metatrader/copier.py,sha256
|
|
22
|
+
bbstrader/metatrader/copier.py,sha256=-cFroX4M1q9rlupU4xLP0N6lR8ZbP_izUOQ2sBe_lFc,31797
|
|
23
23
|
bbstrader/metatrader/rates.py,sha256=0bKyjGnafZ19DwC0-IxXUBJzOdAo-cNmhabwhKLxcos,20585
|
|
24
24
|
bbstrader/metatrader/risk.py,sha256=pwG4q1_uPGgPlokDGVNtd04O6p28yIbgT-evvHuo-Qc,27029
|
|
25
25
|
bbstrader/metatrader/scripts.py,sha256=Yjp7Un-wDTInptHS_rPFpXNKWbVM871VEkaHxsO2MPQ,2115
|
|
26
|
-
bbstrader/metatrader/trade.py,sha256=
|
|
26
|
+
bbstrader/metatrader/trade.py,sha256=Q1cArcpMnovRTED0kwMybcpwPB28rQKXLcJV4jldF0w,81202
|
|
27
27
|
bbstrader/metatrader/utils.py,sha256=lYIvAeiL_ceACmkVNo4-QRopias08KyBUI7THfdj3c0,17103
|
|
28
|
-
bbstrader/models/__init__.py,sha256=
|
|
28
|
+
bbstrader/models/__init__.py,sha256=s2mJrtKePXQaw_PvcrtPCD2mPCdVXP4Myzg0MlLVipo,547
|
|
29
29
|
bbstrader/models/factors.py,sha256=5kSAOS1MHvTZ-Ti03TtjOxl_EvC-V_9e389xeR_82ak,13020
|
|
30
|
-
bbstrader/models/ml.py,sha256=
|
|
30
|
+
bbstrader/models/ml.py,sha256=tCr7YyODl0CDoOUpYqJ1q12ls86Sc-_Fu3b2Y0Z7TJ8,47551
|
|
31
|
+
bbstrader/models/nlp.py,sha256=P7SYaTIqEBldjwYfS6IrO66Y6-ioDXUrCSf3bZxQrDE,28073
|
|
31
32
|
bbstrader/models/optimization.py,sha256=vnks6uxFZdqXgxaZJNxq8z0IH45KZ8yaXo38JhIVKGc,6399
|
|
32
33
|
bbstrader/models/portfolio.py,sha256=r-47Zrn2r7iKCHm5YVtwkbBJXAZGM3QYy-rXCWY9-Bg,8079
|
|
33
|
-
bbstrader/models/risk.py,sha256=
|
|
34
|
+
bbstrader/models/risk.py,sha256=JQOXPshMOru6Eb0AMU6oKCNzg6mlGfL6_tN90lWcVBE,14878
|
|
34
35
|
bbstrader/trading/__init__.py,sha256=ycLyuuxN5SujqtzR9X0Q74UQfK93q2va-GGAXdr-KS8,457
|
|
35
|
-
bbstrader/trading/execution.py,sha256=
|
|
36
|
-
bbstrader/trading/
|
|
37
|
-
bbstrader/trading/
|
|
38
|
-
bbstrader/trading/
|
|
39
|
-
bbstrader-0.2.
|
|
40
|
-
bbstrader-0.2.
|
|
41
|
-
bbstrader-0.2.
|
|
42
|
-
bbstrader-0.2.
|
|
43
|
-
bbstrader-0.2.
|
|
44
|
-
bbstrader-0.2.
|
|
36
|
+
bbstrader/trading/execution.py,sha256=4-XyRll1x8gfF68cTZXjtRF79csDx_oKNI0F71cv1Bw,35028
|
|
37
|
+
bbstrader/trading/scripts.py,sha256=wR5TUrHn-Cd2kzfURXn14VTCEZ-QA8ydwYHayMPK0oI,5720
|
|
38
|
+
bbstrader/trading/strategies.py,sha256=D_M91UwRiFwZKvKFKmz427TPd-dNyWWbhehaP8RI17c,36539
|
|
39
|
+
bbstrader/trading/utils.py,sha256=57dKF9dcRu04oU2VRqydRrzW39dCW2wlDWhVt-sZdRw,1857
|
|
40
|
+
bbstrader-0.2.97.dist-info/licenses/LICENSE,sha256=ZwC_RqqGmOPBUiMDKqLyJZ5HBeHq53LpL7TMRzrJY8c,1094
|
|
41
|
+
bbstrader-0.2.97.dist-info/METADATA,sha256=mBnvqbUXVjE-dl5A5tkdYRuGd_fh2oKU55K-Ryfm9po,11590
|
|
42
|
+
bbstrader-0.2.97.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
43
|
+
bbstrader-0.2.97.dist-info/entry_points.txt,sha256=0yDCbhbgHswOzJnY5wRSM_FjjyMHGvY7lJpSSVh0xtI,54
|
|
44
|
+
bbstrader-0.2.97.dist-info/top_level.txt,sha256=Wwj322jZmxGZ6gD_TdaPiPLjED5ReObm5omerwlmZIg,10
|
|
45
|
+
bbstrader-0.2.97.dist-info/RECORD,,
|
bbstrader/trading/script.py
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import json
|
|
3
|
-
import multiprocessing as mp
|
|
4
|
-
import os
|
|
5
|
-
import sys
|
|
6
|
-
|
|
7
|
-
from bbstrader.btengine import MT5Strategy, Strategy
|
|
8
|
-
from bbstrader.core.utils import load_class, load_module
|
|
9
|
-
from bbstrader.metatrader.trade import create_trade_instance
|
|
10
|
-
from bbstrader.trading.execution import mt5_engine
|
|
11
|
-
|
|
12
|
-
EXECUTION_PATH = os.path.expanduser("~/.bbstrader/execution/execution.py")
|
|
13
|
-
CONFIG_PATH = os.path.expanduser("~/.bbstrader/execution/execution.json")
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def load_config(config_path, strategy_name, account=None):
|
|
17
|
-
if not os.path.exists(config_path):
|
|
18
|
-
raise FileNotFoundError(f"Configuration file not found at {config_path}")
|
|
19
|
-
with open(config_path, "r") as f:
|
|
20
|
-
config = json.load(f)
|
|
21
|
-
try:
|
|
22
|
-
config = config[strategy_name]
|
|
23
|
-
except KeyError:
|
|
24
|
-
raise ValueError(
|
|
25
|
-
f"Strategy {strategy_name} not found in the configuration file."
|
|
26
|
-
)
|
|
27
|
-
if account is not None:
|
|
28
|
-
try:
|
|
29
|
-
config = config[account]
|
|
30
|
-
except KeyError:
|
|
31
|
-
raise ValueError(f"Account {account} not found in the configuration file.")
|
|
32
|
-
if config.get("symbol_list") is None:
|
|
33
|
-
raise ValueError("symbol_list is required in the configuration file.")
|
|
34
|
-
if config.get("trades_kwargs") is None:
|
|
35
|
-
raise ValueError("trades_kwargs is required in the configuration file.")
|
|
36
|
-
return config
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def worker_function(account, args):
|
|
40
|
-
strategy_module = load_module(args.path)
|
|
41
|
-
strategy_class = load_class(strategy_module, args.strategy, (MT5Strategy, Strategy))
|
|
42
|
-
|
|
43
|
-
config = load_config(args.config, args.strategy, account)
|
|
44
|
-
symbol_list = config.pop("symbol_list")
|
|
45
|
-
trades_kwargs = config.pop("trades_kwargs")
|
|
46
|
-
trades = create_trade_instance(symbol_list, trades_kwargs)
|
|
47
|
-
|
|
48
|
-
kwargs = {
|
|
49
|
-
"symbol_list": symbol_list,
|
|
50
|
-
"trades_instances": trades,
|
|
51
|
-
"strategy_cls": strategy_class,
|
|
52
|
-
"account": account,
|
|
53
|
-
**config,
|
|
54
|
-
}
|
|
55
|
-
mt5_engine(account, **kwargs)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def mt5_terminal(args):
|
|
59
|
-
if args.parallel:
|
|
60
|
-
if len(args.account) == 0:
|
|
61
|
-
raise ValueError(
|
|
62
|
-
"account or accounts are required when running in parallel"
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
processes = []
|
|
66
|
-
try:
|
|
67
|
-
for account in args.account:
|
|
68
|
-
p = mp.Process(target=worker_function, args=(account, args))
|
|
69
|
-
p.start()
|
|
70
|
-
processes.append(p)
|
|
71
|
-
|
|
72
|
-
for p in processes:
|
|
73
|
-
p.join()
|
|
74
|
-
except Exception as e:
|
|
75
|
-
print(f"Error in parallel execution: {e}")
|
|
76
|
-
raise e
|
|
77
|
-
except KeyboardInterrupt:
|
|
78
|
-
print("\nTerminating Execution...")
|
|
79
|
-
for p in processes:
|
|
80
|
-
p.terminate()
|
|
81
|
-
for p in processes:
|
|
82
|
-
p.join()
|
|
83
|
-
print("Execution terminated")
|
|
84
|
-
else:
|
|
85
|
-
worker_function(None, args)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def tws_terminal(args):
|
|
89
|
-
raise NotImplementedError("TWS terminal is not implemented yet")
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def execute_strategy(unknown):
|
|
93
|
-
HELP_MSG = """
|
|
94
|
-
Execute a strategy on one or multiple MT5 accounts.
|
|
95
|
-
|
|
96
|
-
Usage:
|
|
97
|
-
python -m bbstrader --run execution [options]
|
|
98
|
-
|
|
99
|
-
Options:
|
|
100
|
-
-s, --strategy: Strategy class name to run
|
|
101
|
-
-a, --account: Account(s) name(s) or ID(s) to run the strategy on (must be the same as in the configuration file)
|
|
102
|
-
-p, --path: Path to the execution file (default: ~/.bbstrader/execution/execution.py)
|
|
103
|
-
-c, --config: Path to the configuration file (default: ~/.bbstrader/execution/execution.json)
|
|
104
|
-
-l, --parallel: Run the strategy in parallel (default: False)
|
|
105
|
-
-t, --terminal: Terminal to use (default: MT5)
|
|
106
|
-
-h, --help: Show this help message and exit
|
|
107
|
-
|
|
108
|
-
Note:
|
|
109
|
-
The configuration file must contain all the required parameters
|
|
110
|
-
to create trade instances for each account and strategy.
|
|
111
|
-
The configuration file must be a dictionary with the following structure:
|
|
112
|
-
If parallel is True:
|
|
113
|
-
{
|
|
114
|
-
"strategy_name": {
|
|
115
|
-
"account_name": {
|
|
116
|
-
"symbol_list": ["symbol1", "symbol2"],
|
|
117
|
-
"trades_kwargs": {"param1": "value1", "param2": "value2"}
|
|
118
|
-
**other_parameters (for the strategy and the execution engine)
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
If parallel is False:
|
|
123
|
-
{
|
|
124
|
-
"strategy_name": {
|
|
125
|
-
"symbol_list": ["symbol1", "symbol2"],
|
|
126
|
-
"trades_kwargs": {"param1": "value1", "param2": "value2"}
|
|
127
|
-
**other_parameters (for the strategy and the execution engine)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
See bbstrader.metatrader.trade.create_trade_instance for more details on the trades_kwargs.
|
|
131
|
-
See bbstrader.trading.execution.MT5ExecutionEngine for more details on the other parameters.
|
|
132
|
-
|
|
133
|
-
All other paramaters must be python built-in types.
|
|
134
|
-
If you have custom type you must set them in your strategy class
|
|
135
|
-
or run the MT5ExecutionEngine directly, don't run on CLI.
|
|
136
|
-
"""
|
|
137
|
-
if "-h" in unknown or "--help" in unknown:
|
|
138
|
-
print(HELP_MSG)
|
|
139
|
-
sys.exit(0)
|
|
140
|
-
|
|
141
|
-
parser = argparse.ArgumentParser()
|
|
142
|
-
parser.add_argument("-s", "--strategy", type=str, required=True)
|
|
143
|
-
parser.add_argument("-a", "--account", type=str, nargs="*", default=[])
|
|
144
|
-
parser.add_argument("-p", "--path", type=str, default=EXECUTION_PATH)
|
|
145
|
-
parser.add_argument("-c", "--config", type=str, default=CONFIG_PATH)
|
|
146
|
-
parser.add_argument("-l", "--parallel", action="store_true")
|
|
147
|
-
parser.add_argument(
|
|
148
|
-
"-t", "--terminal", type=str, default="MT5", choices=["MT5", "TWS"]
|
|
149
|
-
)
|
|
150
|
-
args = parser.parse_args(unknown)
|
|
151
|
-
|
|
152
|
-
if args.terminal == "MT5":
|
|
153
|
-
mt5_terminal(args)
|
|
154
|
-
elif args.terminal == "TWS":
|
|
155
|
-
tws_terminal(args)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|