bbstrader 0.2.5__py3-none-any.whl → 0.2.6__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/__ini__.py CHANGED
@@ -3,11 +3,12 @@ Simplified Investment & Trading Toolkit
3
3
  =======================================
4
4
 
5
5
  """
6
- __author__ = "Bertin Balouki SIMYELI"
7
- __copyright__ = "2023-2025 Bertin Balouki SIMYELI"
8
- __email__ = "bertin@bbstrader.com"
9
- __license__ = "MIT"
10
- __version__ = '0.2.0'
6
+
7
+ __author__ = "Bertin Balouki SIMYELI"
8
+ __copyright__ = "2023-2025 Bertin Balouki SIMYELI"
9
+ __email__ = "bertin@bbstrader.com"
10
+ __license__ = "MIT"
11
+ __version__ = "0.2.0"
11
12
 
12
13
 
13
14
  from bbstrader import btengine # noqa: F401
@@ -124,7 +124,7 @@ class MT5ExecutionHandler(ExecutionHandler):
124
124
  self.events = events
125
125
  self.bardata = data
126
126
  self.logger = kwargs.get("logger")
127
- self.__account = Account()
127
+ self.__account = Account(**kwargs)
128
128
 
129
129
  def _calculate_lot(self, symbol, quantity, price):
130
130
  symbol_type = self.__account.get_symbol_type(symbol)
@@ -10,7 +10,11 @@ import pytz
10
10
 
11
11
  from bbstrader.btengine.data import DataHandler
12
12
  from bbstrader.btengine.event import FillEvent, SignalEvent
13
- from bbstrader.metatrader.account import Account, AdmiralMarktsGroup
13
+ from bbstrader.metatrader.account import (
14
+ Account,
15
+ AdmiralMarktsGroup,
16
+ PepperstoneGroupLimited,
17
+ )
14
18
  from bbstrader.metatrader.rates import Rates
15
19
  from bbstrader.models.optimization import optimized_weights
16
20
  from bbstrader.core.utils import TradeSignal
@@ -122,7 +126,7 @@ class MT5Strategy(Strategy):
122
126
  for asset in self.symbols:
123
127
  if asset not in weights:
124
128
  raise ValueError(f"Risk budget for asset {asset} is missing.")
125
- total_risk = sum(weights.values())
129
+ total_risk = float(round(sum(weights.values())))
126
130
  if not np.isclose(total_risk, 1.0):
127
131
  raise ValueError(f"Risk budget weights must sum to 1. got {total_risk}")
128
132
  return weights
@@ -226,7 +230,7 @@ class MT5Strategy(Strategy):
226
230
  prices = prices.dropna(axis=0, how="any")
227
231
  try:
228
232
  weights = optimized_weights(prices=prices, freq=freq, method=optimer)
229
- return {symbol: weight for symbol, weight in weights.items()}
233
+ return {symbol: abs(weight) for symbol, weight in weights.items()}
230
234
  except Exception:
231
235
  return {symbol: 0.0 for symbol in symbols}
232
236
 
@@ -605,6 +609,7 @@ class MT5Strategy(Strategy):
605
609
  bars: DataHandler = None,
606
610
  mode: Literal["backtest", "live"] = "backtest",
607
611
  tf: str = "D1",
612
+ error: Literal["ignore", "raise"] = None,
608
613
  ) -> Dict[str, np.ndarray | pd.Series] | None:
609
614
  """
610
615
  Get the historical OHLCV value or returns or custum value
@@ -618,6 +623,7 @@ class MT5Strategy(Strategy):
618
623
  mode : Mode of operation for the strategy.
619
624
  window : The lookback period for resquesting the data.
620
625
  tf : The time frame for the strategy.
626
+ error : The error handling method for the function.
621
627
 
622
628
  Returns:
623
629
  asset_values : Historical values of the assets in the symbol list.
@@ -651,6 +657,10 @@ class MT5Strategy(Strategy):
651
657
  if all(len(values) >= window for values in asset_values.values()):
652
658
  return {a: v[-window:] for a, v in asset_values.items()}
653
659
  else:
660
+ if error == "raise":
661
+ raise ValueError("Not enough data to calculate the values.")
662
+ elif error == "ignore":
663
+ return asset_values
654
664
  return None
655
665
 
656
666
  @staticmethod
@@ -763,8 +773,20 @@ class MT5Strategy(Strategy):
763
773
  return dt_to
764
774
 
765
775
  @staticmethod
766
- def get_mt5_equivalent(symbols, type="STK", path: str = None) -> List[str]:
767
- account = Account(path=path)
776
+ def get_mt5_equivalent(symbols, type="STK", **kwargs) -> List[str]:
777
+ """
778
+ Get the MetaTrader 5 equivalent symbols for the symbols in the list.
779
+ This method is used to get the symbols that are available on the MetaTrader 5 platform.
780
+
781
+ Args:
782
+ symbols : The list of symbols to get the MetaTrader 5 equivalent symbols for.
783
+ type : The type of symbols to get (e.g., STK, CFD, etc.).
784
+ **kwargs : Additional keyword arguments for the `bbstrader.metatrader.Account` object.
785
+
786
+ Returns:
787
+ mt5_equivalent : The MetaTrader 5 equivalent symbols for the symbols in the list.
788
+ """
789
+ account = Account(**kwargs)
768
790
  mt5_symbols = account.get_symbols(symbol_type=type)
769
791
  mt5_equivalent = []
770
792
  if account.broker == AdmiralMarktsGroup():
@@ -773,6 +795,11 @@ class MT5Strategy(Strategy):
773
795
  for symbol in symbols:
774
796
  if _s.split(".")[0] == symbol or _s.split("_")[0] == symbol:
775
797
  mt5_equivalent.append(s)
798
+ elif account.broker == PepperstoneGroupLimited():
799
+ for s in mt5_symbols:
800
+ for symbol in symbols:
801
+ if s.split(".")[0] == symbol:
802
+ mt5_equivalent.append(s)
776
803
  return mt5_equivalent
777
804
 
778
805
 
bbstrader/config.py CHANGED
@@ -2,16 +2,22 @@ import logging
2
2
  from pathlib import Path
3
3
  from typing import List
4
4
 
5
- AMG_PATH = "C:\\Program Files\\Admirals Group MT5 Terminal\\terminal64.exe"
6
- FTMO_PATH = "C:\\Program Files\\FTMO MetaTrader 5\\terminal64.exe"
7
- XCB_PATH = "C:\\Program Files\\4xCube MT5 Terminal\\terminal64.exe"
8
- TML_PATH = "C:\\Program Files\\Trinota Markets MetaTrader 5 Terminal\\terminal64.exe"
5
+
6
+ TERMINAL = "\\terminal64.exe"
7
+ BASE_FOLDER = "C:\\Program Files\\"
8
+
9
+ AMG_PATH = BASE_FOLDER + "Admirals Group MT5 Terminal" + TERMINAL
10
+ XCB_PATH = BASE_FOLDER + "4xCube MT5 Terminal" + TERMINAL
11
+ TML_PATH = BASE_FOLDER + "Trinota Markets MetaTrader 5 Terminal" + TERMINAL
12
+ PGL_PATH = BASE_FOLDER + "Pepperstone MetaTrader 5" + TERMINAL
13
+ FTMO_PATH = BASE_FOLDER + "FTMO MetaTrader 5" + TERMINAL
9
14
 
10
15
  BROKERS_PATHS = {
11
16
  "AMG": AMG_PATH,
12
17
  "FTMO": FTMO_PATH,
13
18
  "XCB": XCB_PATH,
14
19
  "TML": TML_PATH,
20
+ "PGL": PGL_PATH,
15
21
  }
16
22
 
17
23
 
@@ -28,6 +28,9 @@ __all__ = [
28
28
  "Broker",
29
29
  "AdmiralMarktsGroup",
30
30
  "JustGlobalMarkets",
31
+ "TrinotaMarkets",
32
+ "XCubeLimited",
33
+ "PepperstoneGroupLimited",
31
34
  "FTMO",
32
35
  ]
33
36
 
@@ -36,7 +39,8 @@ __BROKERS__ = {
36
39
  "JGM": "Just Global Markets Ltd.",
37
40
  "FTMO": "FTMO S.R.O.",
38
41
  "XCB": "4xCube Limited",
39
- "TML": "Trinota Markets (Global) Limited"
42
+ "TML": "Trinota Markets (Global) Limited",
43
+ "PGL": "Pepperstone Group Limited",
40
44
  }
41
45
 
42
46
  BROKERS_TIMEZONES = {
@@ -45,6 +49,7 @@ BROKERS_TIMEZONES = {
45
49
  "FTMO": "Europe/Helsinki",
46
50
  "XCB": "Europe/Helsinki",
47
51
  "TML": "Europe/Helsinki",
52
+ "PGL": "Europe/Helsinki",
48
53
  }
49
54
 
50
55
  _ADMIRAL_MARKETS_URL_ = (
@@ -52,8 +57,6 @@ _ADMIRAL_MARKETS_URL_ = (
52
57
  )
53
58
  _JUST_MARKETS_URL_ = "https://one.justmarkets.link/a/tufvj0xugm/registration/trader"
54
59
  _FTMO_URL_ = "https://trader.ftmo.com/?affiliates=JGmeuQqepAZLMcdOEQRp"
55
- _XCB_URL_ = ""
56
- _TML_URL_ = ""
57
60
  _ADMIRAL_MARKETS_PRODUCTS_ = [
58
61
  "Stocks",
59
62
  "ETFs",
@@ -72,27 +75,26 @@ INIT_MSG = (
72
75
  f"* If you want to trade {', '.join(_ADMIRAL_MARKETS_PRODUCTS_)}, See [{_ADMIRAL_MARKETS_URL_}]\n"
73
76
  f"* If you want to trade {', '.join(_JUST_MARKETS_PRODUCTS_)}, See [{_JUST_MARKETS_URL_}]\n"
74
77
  f"* If you are looking for a prop firm, See [{_FTMO_URL_}]\n"
75
- f"* You can also look at 4xCube Limited [{_XCB_URL_}] \n and Trinota Markets (Global) Limited [{_TML_URL_}]\n"
76
78
  )
77
79
 
78
80
  amg_url = _ADMIRAL_MARKETS_URL_
79
81
  jgm_url = _JUST_MARKETS_URL_
80
82
  ftmo_url = _FTMO_URL_
81
- xcb_url = _XCB_URL_
82
- tml_url = _TML_URL_
83
+
83
84
 
84
85
  _SYMBOLS_TYPE_ = {
85
- "STK": r"\b(Stocks?|Equities?|Shares?)\b",
86
86
  "ETF": r"\b(ETFs?)\b",
87
- "IDX": r"\b(?:Indices?|Cash|Index)\b(?!.*\\(?:UKOIL|USOIL))",
87
+ "BOND": r"\b(Treasuries?)\b",
88
88
  "FX": r"\b(Forex|Exotics?)\b",
89
- "COMD": r"\b(Metals?|Agricultures?|Energies?|OIL|Oil|USOIL|UKOIL)\b",
90
- "FUT": r"\b(Futures?)\b",
89
+ "FUT": r"\b(Futures?|Forwards)\b",
90
+ "STK": r"\b(Stocks?|Equities?|Shares?)\b",
91
+ "IDX": r"\b(?:Indices?|Cash|Index)\b(?!.*\\(?:UKOIL|USOIL))",
92
+ "COMD": r"\b(Commodity|Commodities?|Metals?|Agricultures?|Energies?|OIL|Oil|USOIL|UKOIL)\b",
91
93
  "CRYPTO": r"\b(Cryptos?|Cryptocurrencies|Cryptocurrency)\b",
92
94
  }
93
95
 
94
96
  _COUNTRY_MAP_ = {
95
- "USA": r"\b(US)\b",
97
+ "USA": r"\b(US|USA)\b",
96
98
  "AUS": r"\b(Australia)\b",
97
99
  "BEL": r"\b(Belgium)\b",
98
100
  "DNK": r"\b(Denmark)\b",
@@ -106,6 +108,9 @@ _COUNTRY_MAP_ = {
106
108
  "SWE": r"\b(Sweden)\b",
107
109
  "GBR": r"\b(UK)\b",
108
110
  "CHE": r"\b(Switzerland)\b",
111
+ "HKG": r"\b(Hong Kong)\b",
112
+ "IRL": r"\b(Ireland)\b",
113
+ "AUT": r"\b(Austria)\b",
109
114
  }
110
115
 
111
116
  AMG_EXCHANGES = {
@@ -205,6 +210,9 @@ class Broker(object):
205
210
  def __ne__(self, orther) -> bool:
206
211
  return self.name != orther.name
207
212
 
213
+ def __repr__(self):
214
+ return f"{self.__class__.__name__}({self.name})"
215
+
208
216
 
209
217
  class AdmiralMarktsGroup(Broker):
210
218
  def __init__(self, **kwargs):
@@ -232,6 +240,7 @@ class FTMO(Broker):
232
240
  def timezone(self) -> str:
233
241
  return BROKERS_TIMEZONES["FTMO"]
234
242
 
243
+
235
244
  class XCubeLimited(Broker):
236
245
  def __init__(self, **kwargs):
237
246
  super().__init__("4xCube Limited", **kwargs)
@@ -239,7 +248,8 @@ class XCubeLimited(Broker):
239
248
  @property
240
249
  def timezone(self) -> str:
241
250
  return BROKERS_TIMEZONES["XCB"]
242
-
251
+
252
+
243
253
  class TrinotaMarkets(Broker):
244
254
  def __init__(self, **kwargs):
245
255
  super().__init__("Trinota Markets (Global) Limited", **kwargs)
@@ -249,6 +259,15 @@ class TrinotaMarkets(Broker):
249
259
  return BROKERS_TIMEZONES["TML"]
250
260
 
251
261
 
262
+ class PepperstoneGroupLimited(Broker):
263
+ def __init__(self, **kwargs):
264
+ super().__init__("Pepperstone Group Limited", **kwargs)
265
+
266
+ @property
267
+ def timezone(self) -> str:
268
+ return BROKERS_TIMEZONES["PGL"]
269
+
270
+
252
271
  class AMP(Broker): ...
253
272
 
254
273
 
@@ -258,6 +277,7 @@ BROKERS: Dict[str, Broker] = {
258
277
  "JGM": JustGlobalMarkets(),
259
278
  "XCB": XCubeLimited(),
260
279
  "TML": TrinotaMarkets(),
280
+ "PGL": PepperstoneGroupLimited(),
261
281
  }
262
282
 
263
283
 
@@ -316,8 +336,6 @@ class Account(object):
316
336
  f"For {supported['AMG'].name}, See [{amg_url}]\n"
317
337
  f"For {supported['JGM'].name}, See [{jgm_url}]\n"
318
338
  f"For {supported['FTMO'].name}, See [{ftmo_url}]\n"
319
- f"For {supported['XCB'].name}, See [{xcb_url}]\n"
320
- f"For {supported['TML'].name}, See [{tml_url}]\n"
321
339
  )
322
340
  raise InvalidBroker(message=msg)
323
341
 
@@ -584,6 +602,7 @@ class Account(object):
584
602
  - `COMD`: Commodities (e.g., 'CRUDOIL', 'GOLD')
585
603
  - `FUT`: Futures (e.g., 'USTNote_U4'),
586
604
  - `CRYPTO`: Cryptocurrencies (e.g., 'BTC', 'ETH')
605
+ - `BOND`: Bonds (e.g., 'USTN10YR')
587
606
 
588
607
  check_etf (bool): If True and symbol_type is 'etf', check if the
589
608
  ETF description contains 'ETF'.
@@ -669,6 +688,7 @@ class Account(object):
669
688
  "COMD": "Commodities",
670
689
  "FUT": "Futures",
671
690
  "CRYPTO": "Cryptos Assets",
691
+ "BOND": "Bonds",
672
692
  }
673
693
  print(f"Total {names[symbol_type]}: {len(symbol_list)}")
674
694
 
@@ -684,7 +704,7 @@ class Account(object):
684
704
 
685
705
  def get_symbol_type(
686
706
  self, symbol: str
687
- ) -> Literal["STK", "ETF", "IDX", "FX", "COMD", "FUT", "CRYPTO", "unknown"]:
707
+ ) -> Literal["STK", "ETF", "IDX", "FX", "COMD", "FUT", "CRYPTO", "BOND", "unknown"]:
688
708
  """
689
709
  Determines the type of a given financial instrument symbol.
690
710
 
@@ -692,7 +712,7 @@ class Account(object):
692
712
  symbol (str): The symbol of the financial instrument (e.g., `GOOGL`, `EURUSD`).
693
713
 
694
714
  Returns:
695
- Literal["STK", "ETF", "IDX", "FX", "COMD", "FUT", "CRYPTO", "unknown"]:
715
+ Literal["STK", "ETF", "IDX", "FX", "COMD", "FUT", "CRYPTO", "BOND", "unknown"]:
696
716
  The type of the financial instrument, one of the following:
697
717
 
698
718
  - `STK`: For Stocks (e.g., `GOOGL`)
@@ -702,16 +722,27 @@ class Account(object):
702
722
  - `COMD`: For Commodities (e.g., `CRUDOIL`, `GOLD`)
703
723
  - `FUT` : For Futures (e.g., `USTNote_U4`)
704
724
  - `CRYPTO`: For Cryptocurrencies (e.g., `BTC`, `ETH`)
725
+ - `BOND`: For Bonds (e.g., `USTN10YR`)
705
726
 
706
727
  Returns `unknown` if the type cannot be determined.
707
728
  """
708
729
 
709
730
  patterns = _SYMBOLS_TYPE_
710
731
  info = self.get_symbol_info(symbol)
732
+ indices = self.get_symbols(symbol_type="IDX")
733
+ commodity = self.get_symbols(symbol_type="COMD")
711
734
  if info is not None:
712
735
  for symbol_type, pattern in patterns.items():
713
- match = re.search(pattern, info.path) # , re.IGNORECASE
714
- if match:
736
+ if (
737
+ symbol_type in ["IDX", "COMD"]
738
+ and self.broker == PepperstoneGroupLimited()
739
+ and info.name.endswith("-F")
740
+ and info.name in indices + commodity
741
+ ):
742
+ symbol_type = "FUT"
743
+ pattern = r"\b(Forwards?)\b"
744
+ search = re.compile(pattern)
745
+ if re.search(search, info.path):
715
746
  return symbol_type
716
747
  return "unknown"
717
748
 
@@ -733,14 +764,15 @@ class Account(object):
733
764
  return symbol_list
734
765
 
735
766
  def get_fx_symbols(
736
- self, category: Literal["majors", "minors", "exotics"] = "majors"
767
+ self,
768
+ category: Literal["majors", "minors", "exotics", "crosses", "ndfs"] = "majors",
737
769
  ) -> List[str]:
738
770
  """
739
771
  Retrieves a list of forex symbols belonging to a specific category.
740
772
 
741
773
  Args:
742
774
  category (str, optional): The category of forex symbols to retrieve.
743
- Possible values are 'majors', 'minors', 'exotics'.
775
+ Possible values are 'majors', 'minors', 'exotics', 'crosses', 'ndfs'.
744
776
  Defaults to 'majors'.
745
777
 
746
778
  Returns:
@@ -750,20 +782,22 @@ class Account(object):
750
782
  ValueError: If an unsupported category is provided.
751
783
 
752
784
  Notes:
753
- This mthods works primarly with Admirals Group AS products,
785
+ This mthods works primarly with Admirals Group AS products and Pepperstone Group Limited,
754
786
  For other brokers use `get_symbols()` or this method will use it by default.
755
787
  """
756
- if self.broker != AdmiralMarktsGroup():
788
+ if self.broker not in [AdmiralMarktsGroup(), PepperstoneGroupLimited()]:
757
789
  return self.get_symbols(symbol_type="FX")
758
790
  else:
759
791
  fx_categories = {
760
792
  "majors": r"\b(Majors?)\b",
761
793
  "minors": r"\b(Minors?)\b",
762
794
  "exotics": r"\b(Exotics?)\b",
795
+ "crosses": r"\b(Crosses?)\b",
796
+ "ndfs": r"\b(NDFs?)\b",
763
797
  }
764
798
  return self._get_symbols_by_category("FX", category, fx_categories)
765
799
 
766
- def get_stocks_from_country(self, country_code: str = "USA", etf=True) -> List[str]:
800
+ def get_stocks_from_country(self, country_code: str = "USA", etf=False) -> List[str]:
767
801
  """
768
802
  Retrieves a list of stock symbols from a specific country.
769
803
 
@@ -782,6 +816,9 @@ class Account(object):
782
816
  * **United Kingdom:** GBR
783
817
  * **United States:** USA
784
818
  * **Switzerland:** CHE
819
+ * **Hong Kong:** HKG
820
+ * **Ireland:** IRL
821
+ * **Austria:** AUT
785
822
 
786
823
  Args:
787
824
  country (str, optional): The country code of stocks to retrieve.
@@ -794,11 +831,11 @@ class Account(object):
794
831
  ValueError: If an unsupported country is provided.
795
832
 
796
833
  Notes:
797
- This mthods works primarly with Admirals Group AS products,
834
+ This mthods works primarly with Admirals Group AS products and Pepperstone Group Limited,
798
835
  For other brokers use `get_symbols()` or this method will use it by default.
799
836
  """
800
837
 
801
- if self.broker != AdmiralMarktsGroup():
838
+ if self.broker not in [AdmiralMarktsGroup(), PepperstoneGroupLimited()]:
802
839
  stocks = self.get_symbols(symbol_type="STK")
803
840
  return stocks
804
841
  else:
@@ -11,7 +11,6 @@ from bbstrader.metatrader.utils import TIMEFRAMES, TimeFrame
11
11
 
12
12
  _COMMD_SUPPORTED_ = [
13
13
  "GOLD",
14
- "XAUEUR",
15
14
  "SILVER",
16
15
  "BRENT",
17
16
  "CRUDOIL",
@@ -19,11 +18,17 @@ _COMMD_SUPPORTED_ = [
19
18
  "UKOIL",
20
19
  "XAGEUR",
21
20
  "XAGUSD",
21
+ "XAGAUD",
22
+ "XAGGBP",
22
23
  "XAUAUD",
23
24
  "XAUEUR",
24
25
  "XAUUSD",
25
26
  "XAUGBP",
26
27
  "USOIL",
28
+ "SpotCrude",
29
+ "SpotBrent",
30
+ "NatGas",
31
+ "Soybeans",
27
32
  ]
28
33
 
29
34
  _ADMIRAL_MARKETS_FUTURES_ = [
@@ -54,6 +59,27 @@ _ADMIRAL_MARKETS_FUTURES_ = [
54
59
  "_HSCEI50_",
55
60
  ]
56
61
 
62
+ __PEPPERSTONE_FUTURES__ = [
63
+ "AUS200-F",
64
+ "GER40-F",
65
+ "HK50-F",
66
+ "JPN225-F",
67
+ "UK100-F",
68
+ "US30-F",
69
+ "NAS100-F",
70
+ "US500-F",
71
+ "Crude-F",
72
+ "Brent-F",
73
+ "XAUUSD-F",
74
+ "XAGUSD-F",
75
+ "USDX-F",
76
+ "EUSTX50-F",
77
+ "FRA40-F",
78
+ "GERTEC30-F",
79
+ "SPA35-F",
80
+ "SWI20-F",
81
+ ]
82
+
57
83
  __all__ = ["RiskManagement"]
58
84
 
59
85
 
@@ -461,7 +487,7 @@ class RiskManagement(Account):
461
487
  symbol = self.symbol.split(".")[0]
462
488
  elif self.symbol.endswith("xx"):
463
489
  symbol = self.symbol[:-2]
464
- elif self.symbol.endswith('-'):
490
+ elif self.symbol.endswith("-"):
465
491
  symbol = self.symbol[:-1]
466
492
  else:
467
493
  symbol = self.symbol
@@ -471,8 +497,12 @@ class RiskManagement(Account):
471
497
  f"Supported commodity symbols are: {', '.join(supported)}"
472
498
  )
473
499
  if FUT:
474
- supported = _ADMIRAL_MARKETS_FUTURES_
475
- if self.symbol[:-2] not in supported:
500
+ if "_" in self.symbol:
501
+ symbol = self.symbol[:-2]
502
+ else:
503
+ symbol = self.symbol
504
+ supported = _ADMIRAL_MARKETS_FUTURES_ + __PEPPERSTONE_FUTURES__
505
+ if str(symbol) not in supported:
476
506
  raise ValueError(
477
507
  f"Currency risk calculation for '{self.symbol}' is not a currently supported. \n"
478
508
  f"Supported future symbols are: {', '.join(supported)}"
@@ -604,6 +604,11 @@ class Trade(RiskManagement):
604
604
  result = self.send_order(request)
605
605
  if result.retcode == Mt5.TRADE_RETCODE_DONE:
606
606
  break
607
+ elif result.retcode == Mt5.TRADE_RETCODE_INVALID_VOLUME: #10014
608
+ new_volume = int(request["volume"])
609
+ if new_volume >= 1:
610
+ request["volume"] = new_volume
611
+ result = self.send_order(request)
607
612
  elif result.retcode not in self._retcodes:
608
613
  self._retcodes.append(result.retcode)
609
614
  msg = trade_retcode_message(result.retcode)
@@ -115,7 +115,7 @@ def _mt5_execution(
115
115
  bot_token = kwargs.get("bot_token")
116
116
  chat_id = kwargs.get("chat_id")
117
117
 
118
- expert_ids = kwargs.get("expert_id")
118
+ expert_ids = kwargs.get("expert_ids")
119
119
  if expert_ids is None:
120
120
  expert_ids = list(
121
121
  set([trade.expert_id for trade in trades_instances.values()])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: bbstrader
3
- Version: 0.2.5
3
+ Version: 0.2.6
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/
@@ -24,7 +24,7 @@ Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
25
  Requires-Dist: pandas
26
26
  Requires-Dist: pandas_ta
27
- Requires-Dist: numpy==1.26.4
27
+ Requires-Dist: numpy<2.0.0
28
28
  Requires-Dist: yfinance
29
29
  Requires-Dist: scipy
30
30
  Requires-Dist: hmmlearn
@@ -74,6 +74,13 @@ Dynamic: summary
74
74
  ![bbstrader](https://github.com/bbalouki/bbstrader/blob/main/assets/bbstrader_logo.png?raw=true)
75
75
 
76
76
  [![Documentation Status](https://readthedocs.org/projects/bbstrader/badge/?version=latest)](https://bbstrader.readthedocs.io/en/latest/?badge=latest)
77
+ [![PYPI Version](https://img.shields.io/pypi/v/bbstrader)](https://pypi.org/project/bbstrader/)
78
+ [![PyPi status](https://img.shields.io/pypi/status/bbstrader.svg?maxAge=60)](https://pypi.python.org/pypi/bbstrader)
79
+ [![Supported Python Versions](https://img.shields.io/pypi/pyversions/bbstrader)](https://pypi.org/project/bbstrader/)
80
+ [![PyPI Downloads](https://static.pepy.tech/badge/bbstrader)](https://pepy.tech/projects/bbstrader)
81
+ [![CodeFactor](https://www.codefactor.io/repository/github/bbalouki/bbstrader/badge)](https://www.codefactor.io/repository/github/bbalouki/bbstrader)
82
+ [![LinkedIn](https://img.shields.io/badge/LinkedIn-grey?logo=Linkedin&logoColor=white)](https://www.linkedin.com/in/bertin-balouki-simyeli-15b17a1a6/)
83
+ [![PayPal Me](https://img.shields.io/badge/PayPal%20Me-blue?logo=paypal)](https://paypal.me/bertinbalouki?country.x=SN&locale.x=en_US)
77
84
 
78
85
  [Dcoumentation](https://bbstrader.readthedocs.io/en/latest/index.html)
79
86
 
@@ -86,7 +93,7 @@ BBSTrader is a trading system suite developed for MetaTrader 5 (MT5) and IBKR pl
86
93
  - **Backtesting Module (btengine)** : Enables traders to rigorously test their trading strategies using historical data to evaluate performance before live deployment.
87
94
  - **Trading Strategies Module**: A collection of predefined trading strategies, including ARIMA+GARCH models, Kalman Filters, and Simple Moving Averages, equipped with risk management through Hidden Markov Models.
88
95
  - **MetaTrader5 Module (metatrader)**: Facilitates the direct execution of trading strategies on the MetaTrader 5 platform, supporting real-time trading across multiple financial instruments.
89
- - **Modles Module**: Serves as a framework for implementing various types of financial models (risk managment models, Machine learing models etc).
96
+ - **Models Module**: Serves as a framework for implementing various types of financial models (risk managment models, Machine learing models etc).
90
97
  - **Time serie Module (tseries)** designed for conducting advanced time series analysis in financial markets.
91
98
  It leverages statistical models and algorithms to perform tasks such as cointegration testing, volatility modeling, and filter-based estimation to assist in trading strategy development, market analysis, and financial data exploration.
92
99
 
@@ -1,24 +1,24 @@
1
- bbstrader/__ini__.py,sha256=c2TwxnJi0PtvigdAbAS2wsTAd7CnvwRHUrYr-s4wEsI,567
2
- bbstrader/config.py,sha256=mdzx-xKLnEOpVYkS-0EarEl1BI1Mhcwgp7WgymJUgD0,4086
1
+ bbstrader/__ini__.py,sha256=x9sw2BKGnPi3QF4MwBqJpCpyUgui1StbvBWGNISVAhQ,548
2
+ bbstrader/config.py,sha256=USwdS5qaGbc1Wp5rF0ckP3R1HEZJ8tY0tkZX4CkgNoc,4204
3
3
  bbstrader/tseries.py,sha256=GYNDo03dYEnYHwcQYKpclNDGCwvZ_qAPyou0vhQndS0,69851
4
4
  bbstrader/btengine/__init__.py,sha256=FL0kC0NcsnlTH-yuTv4lu6AexY1wZKN1AQ9rv9MZagQ,3009
5
5
  bbstrader/btengine/backtest.py,sha256=ZzGhoN-_g0cF-OCyk173imze2OXEhykHTUiJ9MowDO8,14582
6
6
  bbstrader/btengine/data.py,sha256=qVDk-cIgtWAeBM5eW08j9MFXBzu4yeWChoFIL9WINYI,26899
7
7
  bbstrader/btengine/event.py,sha256=38mhZH9d53C4x7bZER2B0O6M18txzS4u7zveKyxeP5Y,8603
8
- bbstrader/btengine/execution.py,sha256=DTsONYzc6B3wgPVxhCjWCgQhPofMJQmVOycBVkhIdgM,10368
8
+ bbstrader/btengine/execution.py,sha256=6YfErbqJx2DTy6r4cfZLU8F1YsJG-p8jEhNepdb9Sxc,10376
9
9
  bbstrader/btengine/performance.py,sha256=0meGbMFYzzI9n_09qf4RFpdyqQmCa6C_iu6PvE2POIE,10787
10
10
  bbstrader/btengine/portfolio.py,sha256=M97FONcdZRoSKFFF66LRsO8_KLXr128AI5-LULhMiKk,16167
11
- bbstrader/btengine/strategy.py,sha256=21LSf3Jn2WBbqj9x0a8voU_xw_Q7_Uja-NLX00FRE9U,31749
11
+ bbstrader/btengine/strategy.py,sha256=EiE1P_V0wlFIsA-2U5POQ7qtRMkr1OTH1pQia4jBcGY,32937
12
12
  bbstrader/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  bbstrader/core/data.py,sha256=3_odj9jxokyKU15j1aHTlgLQDjW75tKqGpCUfkpYq2Q,452
14
14
  bbstrader/core/utils.py,sha256=oB4OC0tQDJ1FIaJCuNWUlTzOccHoACSJsP_f7ELrqXQ,1448
15
15
  bbstrader/ibkr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  bbstrader/ibkr/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  bbstrader/metatrader/__init__.py,sha256=rrL_EtecsOCD2Cwhmpgta5CjSGT0K6vzSBiQoyCLe3M,283
18
- bbstrader/metatrader/account.py,sha256=uuHZcc_bJOzrCIrXzMoMtkl41EVPep1jqNrOMfYl14E,56895
18
+ bbstrader/metatrader/account.py,sha256=Le46-lFqYm4VGQn3nPl1DUVCuiuxNi3EVf56kF8gA5Y,58221
19
19
  bbstrader/metatrader/rates.py,sha256=12hNcjRSKcOSjBAhDvpakqAiLaI0ndU6oBhCTIWDzr0,21089
20
- bbstrader/metatrader/risk.py,sha256=pflsprtnEG8BgudmV_IiQvxuUty4bKYnnzZ6s1Yplug,26910
21
- bbstrader/metatrader/trade.py,sha256=zlVzz5-z-1nJe3-BefTEHed6zQj6GOWkjHlALguoov4,72974
20
+ bbstrader/metatrader/risk.py,sha256=OkQ5qOcgy7qHkr6sx4N1B5JJCPBo1HYiIFxGwePTtwc,27479
21
+ bbstrader/metatrader/trade.py,sha256=2H0JSKgaWASaG9UeOnkxI5d12zI5CQ_NBIf4YpEDNCk,73248
22
22
  bbstrader/metatrader/utils.py,sha256=UnwWmmfgY-Cw1V0vL14ehuWr9AhjcJMtVZK8k19b0i4,17672
23
23
  bbstrader/models/__init__.py,sha256=SnGBMQ-zcUIpms3oNeqg7EVDFpg-7OPjNAD8kvi_Q84,508
24
24
  bbstrader/models/factors.py,sha256=dWuXh83hLkwxUp3XwjgUl-r3_cjVcV_s0aFRlSLIfo8,13332
@@ -27,11 +27,11 @@ bbstrader/models/optimization.py,sha256=gp0n9a9vwbUldaNiZUYry_4RP2NW0VFZ2k5NoOkz
27
27
  bbstrader/models/portfolio.py,sha256=-Zq9cmzyOZUlGq9RWfAxClpX0KJZqYZYpc5EGNTcPGI,8302
28
28
  bbstrader/models/risk.py,sha256=IFQoHXxpBwJiifANRgwyAUOp7EgTWBAhfJFCO1sGR3g,15405
29
29
  bbstrader/trading/__init__.py,sha256=2VoxbzfP1XBLVuxJtjRhjEBCtnv9HqwQzfMV4B5mM7M,468
30
- bbstrader/trading/execution.py,sha256=3HlsgXcCqG6P4_F3d5uUQPVE-clsX6_frxyo3fiEuRA,30723
30
+ bbstrader/trading/execution.py,sha256=Iht2WjXbELhtfvxSYZSEXmPCM7SPmQNRP4bS7VIQuFI,30724
31
31
  bbstrader/trading/scripts.py,sha256=pNwHr-3mW87G5fyIMd93wS43NkzOZn4npt4fLNnSUyk,1922
32
32
  bbstrader/trading/strategies.py,sha256=rMvLIhX_8MQg7_Lbo127UqdTRxBUof2m3jgRQTm55p0,37019
33
- bbstrader-0.2.5.dist-info/LICENSE,sha256=P3PBO9RuYPzl6-PkjysTNnwmwMB64ph36Bz9DBj8MS4,1115
34
- bbstrader-0.2.5.dist-info/METADATA,sha256=vvgqvdWfhKFQcQdWlpHheGbOkGBcegJHmkk2NVyyLsc,10399
35
- bbstrader-0.2.5.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
36
- bbstrader-0.2.5.dist-info/top_level.txt,sha256=Wwj322jZmxGZ6gD_TdaPiPLjED5ReObm5omerwlmZIg,10
37
- bbstrader-0.2.5.dist-info/RECORD,,
33
+ bbstrader-0.2.6.dist-info/LICENSE,sha256=P3PBO9RuYPzl6-PkjysTNnwmwMB64ph36Bz9DBj8MS4,1115
34
+ bbstrader-0.2.6.dist-info/METADATA,sha256=lPALTQr6DmLRXW5jpyfkZY4bKXlgF5ihbwRrcQfWd64,11271
35
+ bbstrader-0.2.6.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
36
+ bbstrader-0.2.6.dist-info/top_level.txt,sha256=Wwj322jZmxGZ6gD_TdaPiPLjED5ReObm5omerwlmZIg,10
37
+ bbstrader-0.2.6.dist-info/RECORD,,