bbstrader 0.1.92__py3-none-any.whl → 0.1.94__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.

@@ -138,6 +138,7 @@ class Trade(RiskManagement):
138
138
  - tp
139
139
  - be
140
140
  See the RiskManagement class for more details on these parameters.
141
+ See `bbstrader.metatrader.account.check_mt5_connection()` for more details on how to connect to MT5 terminal.
141
142
  """
142
143
  # Call the parent class constructor first
143
144
  super().__init__(
@@ -160,6 +161,7 @@ class Trade(RiskManagement):
160
161
  self.console_log = console_log
161
162
  self.logger = self._get_logger(logger, console_log)
162
163
  self.tf = kwargs.get("time_frame", 'D1')
164
+ self.kwargs = kwargs
163
165
 
164
166
  self.start_time_hour, self.start_time_minutes = self.start.split(":")
165
167
  self.finishing_time_hour, self.finishing_time_minutes = self.finishing.split(
@@ -174,8 +176,8 @@ class Trade(RiskManagement):
174
176
  self.break_even_points = {}
175
177
  self.trail_after_points = []
176
178
 
177
- self.initialize()
178
- self.select_symbol()
179
+ self.initialize(**kwargs)
180
+ self.select_symbol(**kwargs)
179
181
  self.prepare_symbol()
180
182
 
181
183
  if self.verbose:
@@ -194,7 +196,7 @@ class Trade(RiskManagement):
194
196
  return config_logger(f'{log_path}/{logger}', consol_log)
195
197
  return logger
196
198
 
197
- def initialize(self):
199
+ def initialize(self, **kwargs):
198
200
  """
199
201
  Initializes the MetaTrader 5 (MT5) terminal for trading operations.
200
202
  This method attempts to establish a connection with the MT5 terminal.
@@ -207,7 +209,7 @@ class Trade(RiskManagement):
207
209
  try:
208
210
  if self.verbose:
209
211
  print("\nInitializing the basics.")
210
- check_mt5_connection()
212
+ check_mt5_connection(**kwargs)
211
213
  if self.verbose:
212
214
  print(
213
215
  f"You are running the @{self.expert_name} Expert advisor,"
@@ -216,7 +218,7 @@ class Trade(RiskManagement):
216
218
  except Exception as e:
217
219
  self.logger.error(f"During initialization: {e}")
218
220
 
219
- def select_symbol(self):
221
+ def select_symbol(self, **kwargs):
220
222
  """
221
223
  Selects the trading symbol in the MetaTrader 5 (MT5) terminal.
222
224
  This method ensures that the specified trading
@@ -228,6 +230,7 @@ class Trade(RiskManagement):
228
230
  MT5TerminalError: If symbole selection fails.
229
231
  """
230
232
  try:
233
+ check_mt5_connection(**kwargs)
231
234
  if not Mt5.symbol_select(self.symbol, True):
232
235
  raise_mt5_error(message=INIT_MSG)
233
236
  except Exception as e:
@@ -848,10 +851,11 @@ class Trade(RiskManagement):
848
851
  positions = self.get_positions(symbol=self.symbol)
849
852
  if positions is not None:
850
853
  positions = [position for position in positions if position.magic == id]
851
- profit = 0.0
852
- balance = self.get_account_info().balance
853
- target = round((balance * self.target)/100, 2)
854
- if positions is not None or len(positions) != 0:
854
+
855
+ if positions is not None:
856
+ profit = 0.0
857
+ balance = self.get_account_info().balance
858
+ target = round((balance * self.target)/100, 2)
855
859
  for position in positions:
856
860
  profit += position.profit
857
861
  fees = self.get_stats()[0]["average_fee"] * len(positions)
@@ -1489,6 +1493,7 @@ def create_trade_instance(
1489
1493
  daily_risk: Optional[Dict[str, float]] = None,
1490
1494
  max_risk: Optional[Dict[str, float]] = None,
1491
1495
  pchange_sl: Optional[Dict[str, float] | float] = None,
1496
+ **kwargs
1492
1497
  ) -> Dict[str, Trade]:
1493
1498
  """
1494
1499
  Creates Trade instances for each symbol provided.
@@ -3,4 +3,8 @@ The `models` module provides a foundational framework for implementing various q
3
3
 
4
4
  It is designed to be a versatile base module for different types of models used in financial analysis and trading.
5
5
  """
6
- from bbstrader.models.risk import *
6
+ from bbstrader.models.risk import *
7
+ from bbstrader.models.optimization import *
8
+ from bbstrader.models.portfolios import *
9
+ from bbstrader.models.factors import *
10
+ from bbstrader.models.ml import *
@@ -6,7 +6,14 @@ from pypfopt.efficient_frontier import EfficientFrontier
6
6
  from pypfopt.hierarchical_portfolio import HRPOpt
7
7
  import warnings
8
8
 
9
- def markowitz_weights(prices=None, freq=252):
9
+ __all__ = [
10
+ 'markowitz_weights',
11
+ 'hierarchical_risk_parity',
12
+ 'equal_weighted',
13
+ 'optimized_weights'
14
+ ]
15
+
16
+ def markowitz_weights(prices=None, rfr=0.0, freq=252):
10
17
  """
11
18
  Calculates optimal portfolio weights using Markowitz's mean-variance optimization (Max Sharpe Ratio) with multiple solvers.
12
19
 
@@ -45,7 +52,7 @@ def markowitz_weights(prices=None, freq=252):
45
52
  weight_bounds=(0, 1),
46
53
  solver=solver)
47
54
  try:
48
- weights = ef.max_sharpe()
55
+ weights = ef.max_sharpe(risk_free_rate=rfr)
49
56
  return ef.clean_weights()
50
57
  except Exception as e:
51
58
  print(f"Solver {solver} failed with error: {e}")
@@ -83,7 +90,7 @@ def hierarchical_risk_parity(prices=None, returns=None, freq=252):
83
90
  if returns is None and prices is None:
84
91
  raise ValueError("Either prices or returns must be provided")
85
92
  if returns is None:
86
- returns = prices.pct_change().dropna()
93
+ returns = prices.pct_change().dropna(how='all')
87
94
  # Remove duplicate columns and index
88
95
  returns = returns.loc[:, ~returns.columns.duplicated()]
89
96
  returns = returns.loc[~returns.index.duplicated(keep='first')]
@@ -128,7 +135,7 @@ def equal_weighted(prices=None, returns=None, round_digits=5):
128
135
  columns = returns.columns
129
136
  return {col: round(1/n, round_digits) for col in columns}
130
137
 
131
- def optimized_weights(prices=None, returns=None, freq=252, method='markowitz'):
138
+ def optimized_weights(prices=None, returns=None, rfr=0.0, freq=252, method='equal'):
132
139
  """
133
140
  Selects an optimization method to calculate portfolio weights based on user preference.
134
141
 
@@ -161,7 +168,7 @@ def optimized_weights(prices=None, returns=None, freq=252, method='markowitz'):
161
168
  - 'equal': Equal weighting across all assets
162
169
  """
163
170
  if method == 'markowitz':
164
- return markowitz_weights(prices=prices, freq=freq)
171
+ return markowitz_weights(prices=prices, rfr=rfr, freq=freq)
165
172
  elif method == 'hrp':
166
173
  return hierarchical_risk_parity(prices=prices, returns=returns, freq=freq)
167
174
  elif method == 'equal':
@@ -10,6 +10,9 @@ from bbstrader.models.optimization import (
10
10
  equal_weighted
11
11
  )
12
12
 
13
+ __all__ = [
14
+ 'EigenPortfolios'
15
+ ]
13
16
 
14
17
  class EigenPortfolios(object):
15
18
  """
bbstrader/models/risk.py CHANGED
@@ -310,7 +310,15 @@ class HMMRiskManager(RiskModel):
310
310
  and data filtered up to the end date if specified.
311
311
  """
312
312
  df = data_frame.copy()
313
- df['Returns'] = df['Adj Close'].pct_change()
313
+ if 'Returns' or 'returns' not in df.columns:
314
+ if 'Close' in df.columns:
315
+ df['Returns'] = df['Close'].pct_change()
316
+ elif 'Adj Close' in df.columns:
317
+ df['Returns'] = df['Adj Close'].pct_change()
318
+ else:
319
+ raise ValueError("No 'Close' or 'Adj Close' columns found.")
320
+ elif 'returns' in df.columns:
321
+ df.rename(columns={'returns': 'Returns'}, inplace=True)
314
322
  if end is not None:
315
323
  df = df[:end.strftime('%Y-%m-%d')]
316
324
  df.dropna(inplace=True)
@@ -78,10 +78,11 @@ EXIT_SIGNAL_ACTIONS = {
78
78
 
79
79
  def _mt5_execution(
80
80
  symbol_list, trades_instances, strategy_cls, /,
81
- mm, trail, stop_trail, trail_after_points, be_plus_points, show_positions_orders,
82
- time_frame, iter_time, use_trade_time, period, period_end_action, closing_pnl, trading_days,
81
+ mm, optimizer, trail, stop_trail, trail_after_points, be_plus_points, show_positions_orders,
82
+ iter_time, use_trade_time, period, period_end_action, closing_pnl, trading_days,
83
83
  comment, **kwargs):
84
84
  symbols = symbol_list.copy()
85
+ time_frame = kwargs.get('time_frame', '15m')
85
86
  STRATEGY = kwargs.get('strategy_name')
86
87
  mtrades = kwargs.get('max_trades')
87
88
  notify = kwargs.get('notify', False)
@@ -89,13 +90,23 @@ def _mt5_execution(
89
90
  telegram = kwargs.get('telegram', False)
90
91
  bot_token = kwargs.get('bot_token')
91
92
  chat_id = kwargs.get('chat_id')
93
+
94
+ def update_risk(weights):
95
+ if weights is not None:
96
+ for symbol in symbols:
97
+ if symbol not in weights:
98
+ continue
99
+ trade = trades_instances[symbol]
100
+ trade.dailydd = round(weights[symbol], 5)
92
101
 
93
102
  def _send_notification(signal):
94
103
  send_message(message=signal, notify_me=notify,
95
104
  telegram=telegram, token=bot_token, chat_id=chat_id)
96
105
 
97
106
  logger = trades_instances[symbols[0]].logger
98
- max_trades = {symbol: mtrades[symbol] for symbol in symbols}
107
+ max_trades = {symbol: mtrades[symbol]
108
+ if mtrades is not None and symbol in mtrades
109
+ else trades_instances[symbol].max_trade() for symbol in symbols}
99
110
  if comment is None:
100
111
  trade = trades_instances[symbols[0]]
101
112
  comment = f"{trade.expert_name}@{trade.version}"
@@ -114,7 +125,7 @@ def _mt5_execution(
114
125
  long_market = {symbol: False for symbol in symbols}
115
126
  short_market = {symbol: False for symbol in symbols}
116
127
  try:
117
- check_mt5_connection()
128
+ check_mt5_connection(**kwargs)
118
129
  strategy: MT5Strategy = strategy_cls(symbol_list=symbols, mode='live', **kwargs)
119
130
  except Exception as e:
120
131
  logger.error(f"Initializing strategy, {e}, STRATEGY={STRATEGY}")
@@ -124,7 +135,7 @@ def _mt5_execution(
124
135
 
125
136
  while True:
126
137
  try:
127
- check_mt5_connection()
138
+ check_mt5_connection(**kwargs)
128
139
  current_date = datetime.now()
129
140
  today = current_date.strftime("%A").lower()
130
141
  time.sleep(0.5)
@@ -158,14 +169,18 @@ def _mt5_execution(
158
169
  continue
159
170
  time.sleep(0.5)
160
171
  try:
161
- check_mt5_connection()
172
+ check_mt5_connection(**kwargs)
162
173
  signals = strategy.calculate_signals()
174
+ weights = None
175
+ if hasattr(strategy, 'apply_risk_management'):
176
+ weights = strategy.apply_risk_management(optimizer)
177
+ update_risk(weights)
163
178
  except Exception as e:
164
179
  logger.error(f"Calculating signal, {e}, STRATEGY={STRATEGY}")
165
180
  continue
166
181
  for symbol in symbols:
167
182
  try:
168
- check_mt5_connection()
183
+ check_mt5_connection(**kwargs)
169
184
  trade: Trade = trades_instances[symbol]
170
185
  tfmsg = f"Time Frame Not completed !!! SYMBOL={trade.symbol}, STRATEGY={STRATEGY}"
171
186
  riskmsg = f"Risk not allowed !!! SYMBOL={trade.symbol}, STRATEGY={STRATEGY}"
@@ -181,7 +196,7 @@ def _mt5_execution(
181
196
  if signal is not None:
182
197
  signal = 'BMKT' if signal == 'LONG' else signal
183
198
  signal = 'SMKT' if signal == 'SHORT' else signal
184
- info = f"SIGNAL = {signal}, SYMBOL={trade.symbol}, STRATEGY={STRATEGY}"
199
+ info = f"SIGNAL = {signal}, SYMBOL={trade.symbol}, STRATEGY={STRATEGY}, TIMEFRAME={time_frame}"
185
200
  msg = f"Sending {signal} Order ... SYMBOL={trade.symbol}, STRATEGY={STRATEGY}"
186
201
  if signal not in EXIT_SIGNAL_ACTIONS:
187
202
  logger.info(info)
@@ -258,7 +273,7 @@ def _mt5_execution(
258
273
  )
259
274
  try:
260
275
  FRIDAY = 'friday'
261
- check_mt5_connection()
276
+ check_mt5_connection(**kwargs)
262
277
  day_end = all(trade.days_end() for trade in trades_instances.values())
263
278
  if closing_pnl is not None:
264
279
  closing = all(trade.positive_profit(id=trade.expert_id, th=closing_pnl)
@@ -436,12 +451,12 @@ class MT5ExecutionEngine():
436
451
  strategy_cls: Strategy,
437
452
  /,
438
453
  mm: bool = True,
454
+ optimizer: str = 'equal',
439
455
  trail: bool = True,
440
456
  stop_trail: Optional[int] = None,
441
457
  trail_after_points: Optional[int] = None,
442
458
  be_plus_points: Optional[int] = None,
443
459
  show_positions_orders: bool = False,
444
- time_frame: str = '15m',
445
460
  iter_time: int | float = 5,
446
461
  use_trade_time: bool = True,
447
462
  period: Literal['day', 'week', 'month'] = 'week',
@@ -450,15 +465,16 @@ class MT5ExecutionEngine():
450
465
  trading_days: Optional[List[str]] = TradingDays,
451
466
  comment: Optional[str] = None,
452
467
  **kwargs
453
- ):
468
+ ):
454
469
  """
455
470
  Args:
456
471
  symbol_list : List of symbols to trade
457
472
  trades_instances : Dictionary of Trade instances
458
473
  strategy_cls : Strategy class to use for trading
459
474
  mm : Enable Money Management. Defaults to False.
475
+ optimizer : Risk management optimizer. Defaults to 'equal'.
476
+ See `bbstrader.models.optimization` module for more information.
460
477
  show_positions_orders : Print open positions and orders. Defaults to False.
461
- time_frame : Time frame to trade. Defaults to '15m'.
462
478
  iter_time : Interval to check for signals and `mm`. Defaults to 5.
463
479
  use_trade_time : Open trades after the time is completed. Defaults to True.
464
480
  period : Period to trade. Defaults to 'week'.
@@ -468,6 +484,7 @@ class MT5ExecutionEngine():
468
484
  trading_days : Trading days in a week. Defaults to monday to friday.
469
485
  comment: Comment for trades. Defaults to None.
470
486
  **kwargs: Additional keyword arguments
487
+ _ time_frame : Time frame to trade. Defaults to '15m'.
471
488
  - strategy_name (Optional[str]): Strategy name. Defaults to None.
472
489
  - max_trades (Dict[str, int]): Maximum trades per symbol. Defaults to None.
473
490
  - notify (bool): Enable notifications. Defaults to False.
@@ -492,17 +509,18 @@ class MT5ExecutionEngine():
492
509
 
493
510
  4. All strategies must generate signals for backtesting and live trading.
494
511
  See the `bbstrader.trading.strategies` module for more information on how to create custom strategies.
512
+ See `bbstrader.metatrader.account.check_mt5_connection()` for more details on how to connect to MT5 terminal.
495
513
  """
496
514
  self.symbol_list = symbol_list
497
515
  self.trades_instances = trades_instances
498
516
  self.strategy_cls = strategy_cls
499
517
  self.mm = mm
518
+ self.optimizer = optimizer
500
519
  self.trail = trail
501
520
  self.stop_trail = stop_trail
502
521
  self.trail_after_points = trail_after_points
503
522
  self.be_plus_points = be_plus_points
504
523
  self.show_positions_orders = show_positions_orders
505
- self.time_frame = time_frame
506
524
  self.iter_time = iter_time
507
525
  self.use_trade_time = use_trade_time
508
526
  self.period = period
@@ -512,19 +530,24 @@ class MT5ExecutionEngine():
512
530
  self.comment = comment
513
531
  self.kwargs = kwargs
514
532
 
533
+ def __repr__(self):
534
+ trades = self.trades_instances.keys()
535
+ s = self.strategy_cls.__name__
536
+ return f"MT5ExecutionEngine(Symbols={list(trades)}, Strategy={s})"
537
+
515
538
  def run(self):
516
- check_mt5_connection()
539
+ check_mt5_connection(**self.kwargs)
517
540
  _mt5_execution(
518
541
  self.symbol_list,
519
542
  self.trades_instances,
520
543
  self.strategy_cls,
521
544
  mm=self.mm,
545
+ optimizer=self.optimizer,
522
546
  trail=self.trail,
523
547
  stop_trail=self.stop_trail,
524
548
  trail_after_points=self.trail_after_points,
525
549
  be_plus_points=self.be_plus_points,
526
550
  show_positions_orders=self.show_positions_orders,
527
- time_frame=self.time_frame,
528
551
  iter_time=self.iter_time,
529
552
  use_trade_time=self.use_trade_time,
530
553
  period=self.period,
@@ -80,17 +80,17 @@ class SMAStrategy(Strategy):
80
80
  self.symbol_list = symbol_list or self.bars.symbol_list
81
81
  self.mode = mode
82
82
 
83
+ self.kwargs = kwargs
83
84
  self.short_window = kwargs.get("short_window", 50)
84
85
  self.long_window = kwargs.get("long_window", 200)
85
86
  self.tf = kwargs.get("time_frame", 'D1')
86
87
  self.qty = get_quantities(
87
88
  kwargs.get('quantities', 100), self.symbol_list)
88
89
  self.sd = kwargs.get("session_duration", 23.0)
89
- self.risk_models = build_hmm_models(self.symbol_list, **kwargs)
90
+ self.risk_models = build_hmm_models(self.symbol_list, **self.kwargs)
90
91
  self.risk_window = kwargs.get("risk_window", self.long_window)
91
92
  self.bought = self._calculate_initial_bought()
92
93
 
93
-
94
94
  def _calculate_initial_bought(self):
95
95
  bought = {}
96
96
  for s in self.symbol_list:
@@ -151,13 +151,13 @@ class SMAStrategy(Strategy):
151
151
  signal = SignalEvent(
152
152
  1, s, dt, 'SHORT', quantity=self.qty[s], price=price)
153
153
  self.bought[s] = 'SHORT'
154
- signals[s] = signal
154
+ signals[s] = signal
155
155
  return signals
156
156
 
157
157
  def get_live_data(self):
158
158
  symbol_data = {symbol: None for symbol in self.symbol_list}
159
159
  for symbol in self.symbol_list:
160
- sig_rate = Rates(symbol, self.tf, 0, self.risk_window)
160
+ sig_rate = Rates(symbol, self.tf, 0, self.risk_window+2, **self.kwargs)
161
161
  hmm_data = sig_rate.returns.values
162
162
  prices = sig_rate.close.values
163
163
  current_regime = self.risk_models[symbol].which_trade_allowed(hmm_data)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bbstrader
3
- Version: 0.1.92
3
+ Version: 0.1.94
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/
@@ -23,7 +23,7 @@ Classifier: License :: OSI Approved :: MIT License
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
25
  Requires-Dist: pandas
26
- Requires-Dist: numpy ==1.26.4
26
+ Requires-Dist: numpy==1.26.4
27
27
  Requires-Dist: yfinance
28
28
  Requires-Dist: scipy
29
29
  Requires-Dist: hmmlearn
@@ -47,8 +47,10 @@ Requires-Dist: scikit-learn
47
47
  Requires-Dist: notify-py
48
48
  Requires-Dist: python-telegram-bot
49
49
  Requires-Dist: pyportfolioopt
50
+ Requires-Dist: eodhd
51
+ Requires-Dist: financetoolkit
50
52
  Provides-Extra: mt5
51
- Requires-Dist: MetaTrader5 ; extra == 'mt5'
53
+ Requires-Dist: MetaTrader5; extra == "mt5"
52
54
 
53
55
  # Simplified Investment & Trading Toolkit
54
56
  ![bbstrader](https://github.com/bbalouki/bbstrader/blob/main/assets/bbstrader_logo.png?raw=true)
@@ -0,0 +1,32 @@
1
+ bbstrader/__ini__.py,sha256=rCTy-3g2RlDAgIZ7cSET9-I74MwuCXpp-xGVTFS8NNc,482
2
+ bbstrader/config.py,sha256=_AD_Cd-w5zyabm1CBPNGhzcZuSjThB7jyzTcjbrIlUQ,3618
3
+ bbstrader/tseries.py,sha256=qJKLxHnPOjB7dXon-ITK7vU1fAuvl8evzET6lSSnijQ,53572
4
+ bbstrader/btengine/__init__.py,sha256=OaXZTjgDwqWrjPq-CNE4kJkmriKXt9t5pIghW1MDTeo,2911
5
+ bbstrader/btengine/backtest.py,sha256=A3S84jpGTE_zhguOEGoGu6H_4ws4Iq5sf0n7TZaUYfQ,14615
6
+ bbstrader/btengine/data.py,sha256=3bdd50hMrszNmcOXd8BYtkjTjg56fiThW2EJsItsCJA,26509
7
+ bbstrader/btengine/event.py,sha256=zF_ST4tcjV5uJJVV1IbRXQgCLbca2R2fmE7A2MaIno4,8748
8
+ bbstrader/btengine/execution.py,sha256=Fs6Hk64DxEOEVzAjsQ3CIVvYifWLLgkDjOixSh_Ghsc,10282
9
+ bbstrader/btengine/performance.py,sha256=WTYzB50lUD5aShPIEebbQPlaC2NVW6VfxdgGHjcIIAw,10707
10
+ bbstrader/btengine/portfolio.py,sha256=wCRmGxaZvihUPlXIlZp9cQo9fqPP-Tk5oALjknMfnos,16055
11
+ bbstrader/btengine/strategy.py,sha256=6IN1KQ-a-IQgbCEOflKTtGh-ouztwsVjik6TuMg6CY0,30210
12
+ bbstrader/metatrader/__init__.py,sha256=OLVOB_EieEb1P72I8V4Vem8kQWJ__D_L3c_wfwqY-9k,211
13
+ bbstrader/metatrader/account.py,sha256=tkcAEgFIYZwtFRQc07lXQQFWRqglzR4H4LjX2BDRvj8,56371
14
+ bbstrader/metatrader/rates.py,sha256=RLzeq26LJ8dzFccgTcMjSUut4lsnt7xrWPXf5Z8xVuQ,21073
15
+ bbstrader/metatrader/risk.py,sha256=uLarOF-g9-RBdJuKSmIfT5WrPn47bmrvMxP21pQg4xo,26793
16
+ bbstrader/metatrader/trade.py,sha256=xAdwe00qNP0qeDzXGCK1_i4lsa9LpUkhbj82XqwJe6Y,70464
17
+ bbstrader/metatrader/utils.py,sha256=BTaZun4DKWpCxBBzY0SLQqqz7n_7F_R1F59APfyaa3E,17666
18
+ bbstrader/models/__init__.py,sha256=mpxtXYEcE8hwNDbzJf8MRqnBIa2T1voraEk0U0ri53c,437
19
+ bbstrader/models/factors.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ bbstrader/models/ml.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ bbstrader/models/optimization.py,sha256=JlMsda9L-ADSgw4YPE4o3CsL1Yyxfeahf9kUb-EZqqM,6699
22
+ bbstrader/models/portfolios.py,sha256=dFTZ3maRVY_O3UOIoRlLCbAow3SiLTQYt1q5DNaRUxE,8223
23
+ bbstrader/models/risk.py,sha256=k1f78_a6oYk24kv-iURecsSfpgCTWi6IpLsoR4LwnWg,15530
24
+ bbstrader/trading/__init__.py,sha256=3CCzV5rQbH8NthjDJhD0_2FABvpiCmkeC9cVeoW7bi4,438
25
+ bbstrader/trading/execution.py,sha256=EhrTtDVV1Dz7T7_RglY4he3ZZMzijgl5tcRhQvbfIWA,26545
26
+ bbstrader/trading/scripts.py,sha256=rQmnG_4F_MuUEc96RXpAQT4kXrC-FkscsgHKgDAR_-Y,1902
27
+ bbstrader/trading/strategies.py,sha256=6bj-xXIEzhTfWrGHAkjWJg7U1OkARu7YzoaWeSrfuZY,36460
28
+ bbstrader-0.1.94.dist-info/LICENSE,sha256=1EudjwwP2oTJy8Vh0e-Kzv8VZZU95y-t6c3DYhR51uc,1115
29
+ bbstrader-0.1.94.dist-info/METADATA,sha256=JKdBaA3tjT_Deirxlf_2jSQkvlvZh6UxdVqWMph84mI,9983
30
+ bbstrader-0.1.94.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
31
+ bbstrader-0.1.94.dist-info/top_level.txt,sha256=Wwj322jZmxGZ6gD_TdaPiPLjED5ReObm5omerwlmZIg,10
32
+ bbstrader-0.1.94.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,32 +0,0 @@
1
- bbstrader/__ini__.py,sha256=rCTy-3g2RlDAgIZ7cSET9-I74MwuCXpp-xGVTFS8NNc,482
2
- bbstrader/config.py,sha256=_AD_Cd-w5zyabm1CBPNGhzcZuSjThB7jyzTcjbrIlUQ,3618
3
- bbstrader/tseries.py,sha256=qJKLxHnPOjB7dXon-ITK7vU1fAuvl8evzET6lSSnijQ,53572
4
- bbstrader/btengine/__init__.py,sha256=OaXZTjgDwqWrjPq-CNE4kJkmriKXt9t5pIghW1MDTeo,2911
5
- bbstrader/btengine/backtest.py,sha256=bgQNiS_kb1zWyX_8_OIDGTBlHGC5pw7ZMIQ5csYDahA,14115
6
- bbstrader/btengine/data.py,sha256=A6jUqDnjl-w1OSzbLLPfS1WfJ8Se25AqigJs9pbe0wc,17966
7
- bbstrader/btengine/event.py,sha256=zF_ST4tcjV5uJJVV1IbRXQgCLbca2R2fmE7A2MaIno4,8748
8
- bbstrader/btengine/execution.py,sha256=i-vI9LGqVtEIKfH_T5Airv-gI4t1X75CfuFIuQdogkA,10187
9
- bbstrader/btengine/performance.py,sha256=bKwj1_CSygvggLKTXPASp2eWhDdwyCf06ayUaXwdh4E,10655
10
- bbstrader/btengine/portfolio.py,sha256=9Jw0UA2gPu-YkUNenoMSHt8t-axtbl6veWXgcRMTQ14,16074
11
- bbstrader/btengine/strategy.py,sha256=w5vwlpJNIVjslaHprWDr-3j-JJPiO1EvqeyrJmorByE,25721
12
- bbstrader/metatrader/__init__.py,sha256=OLVOB_EieEb1P72I8V4Vem8kQWJ__D_L3c_wfwqY-9k,211
13
- bbstrader/metatrader/account.py,sha256=hVH83vnAdfMOzUsF9PiWelqxa7HaLSTpCVlUEePnSZg,53912
14
- bbstrader/metatrader/rates.py,sha256=1dJHbVqoT41m3EhF0wRe7dSGe5Kf3o5Maskkw-i5qsQ,20810
15
- bbstrader/metatrader/risk.py,sha256=8FcLY8pgV8_rxAcjx179sdqaMu66wl-fDFPZvdihfUw,25953
16
- bbstrader/metatrader/trade.py,sha256=uigDah9n_rVJiwSslTAArLP94sde1dxYyGyRVIPPgb4,70210
17
- bbstrader/metatrader/utils.py,sha256=BTaZun4DKWpCxBBzY0SLQqqz7n_7F_R1F59APfyaa3E,17666
18
- bbstrader/models/__init__.py,sha256=6tAj9V9vgwesgPVMKznwRB3k8-Ec8Q73Di5p2UO0qlA,274
19
- bbstrader/models/factors.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- bbstrader/models/ml.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- bbstrader/models/optimization.py,sha256=0ZOCinveMCSxpL4gTBO5lbZ6jb1HXp0CeIjO-_fNGro,6521
22
- bbstrader/models/portfolios.py,sha256=TyLcYwxW86t1qH6YS5xBaiKB9Owezq3ovffjR0Othlw,8184
23
- bbstrader/models/risk.py,sha256=Pm_WoGI-vtPW75fwo_7ptF2Br-xQYBwrAAOIgqDQmy8,15120
24
- bbstrader/trading/__init__.py,sha256=3CCzV5rQbH8NthjDJhD0_2FABvpiCmkeC9cVeoW7bi4,438
25
- bbstrader/trading/execution.py,sha256=Ze_YFrdgU9mRZsS4J08lZNE77HBwxrun5rdqHkS4dzE,25348
26
- bbstrader/trading/scripts.py,sha256=rQmnG_4F_MuUEc96RXpAQT4kXrC-FkscsgHKgDAR_-Y,1902
27
- bbstrader/trading/strategies.py,sha256=ztKNL4Nmlb-4N8_cq0OJyn3E2cRcdKdKu3FeTbZrHsU,36402
28
- bbstrader-0.1.92.dist-info/LICENSE,sha256=1EudjwwP2oTJy8Vh0e-Kzv8VZZU95y-t6c3DYhR51uc,1115
29
- bbstrader-0.1.92.dist-info/METADATA,sha256=LZdzZUHKait-lIvprJ85AxfRuHp8VE5QPS69y8uZIIs,9932
30
- bbstrader-0.1.92.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
31
- bbstrader-0.1.92.dist-info/top_level.txt,sha256=Wwj322jZmxGZ6gD_TdaPiPLjED5ReObm5omerwlmZIg,10
32
- bbstrader-0.1.92.dist-info/RECORD,,