bbstrader 0.3.5__py3-none-any.whl → 0.3.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/tseries.py CHANGED
@@ -24,7 +24,6 @@ from statsmodels.tsa.vector_ar.var_model import VAR
24
24
  from statsmodels.tsa.vector_ar.vecm import coint_johansen
25
25
  from tqdm import tqdm
26
26
 
27
-
28
27
  __all__ = [
29
28
  "run_kalman_filter",
30
29
  "KalmanFilterModel",
@@ -746,32 +745,40 @@ def select_assets(df: pd.DataFrame, n=100, start=None, end=None, rolling_window=
746
745
 
747
746
 
748
747
  def compute_pair_metrics(security: pd.Series, candidates: pd.DataFrame):
749
- """
750
- Calculates statistical and econometric metrics for a target security and a set of candidate securities.
751
- These metrics are useful in financial modeling and pairs trading strategies,
752
- providing information about drift, volatility, correlation, and cointegration.
748
+ """Calculate statistical and econometric metrics for a security pair.
753
749
 
754
- Args:
755
- security (pd.Series): A time-series of the target security's prices.
756
- The name of the Series should correspond to the security's identifier (e.g., ticker symbol).
757
- candidates (pd.DataFrame): A DataFrame where each column represents a time-series of prices
758
- for candidate securities to be evaluated against the target security.
750
+ These metrics are useful in financial modeling and pairs trading strategies,
751
+ providing information about drift, volatility, correlation, and
752
+ cointegration.
759
753
 
760
- Returns:
761
- pd.DataFrame: A DataFrame combining:
762
- Drift: Estimated drift of spreads between the target security and each candidate.
763
- Volatility: Standard deviation of spreads.
764
- Correlation:
765
- ``corr``: Correlation of normalized prices between the target and each candidate.
766
- ``corr_ret``: Correlation of returns (percentage change) between the target and each candidate.
767
- Cointegration metrics:
768
- Engle-Granger test statistics (``t1``, ``t2``) and p-values (``p1``, ``p2``).
769
- Johansen test trace statistics (``trace0``, ``trace1``) and selected lag order (``k_ar_diff``).
754
+ Parameters
755
+ ----------
756
+ security : pd.Series
757
+ A time-series of the target security's prices. The name of the
758
+ Series should correspond to the security's identifier (e.g., ticker
759
+ symbol).
760
+ candidates : pd.DataFrame
761
+ A DataFrame where each column represents a time-series of prices
762
+ for candidate securities to be evaluated against the target security.
763
+
764
+ Returns
765
+ -------
766
+ pd.DataFrame
767
+ A DataFrame containing the following metrics as columns:
768
+ * ``Drift``: Estimated drift of spreads.
769
+ * ``Volatility``: Standard deviation of spreads.
770
+ * ``corr``: Correlation of normalized prices.
771
+ * ``corr_ret``: Correlation of returns (percentage change).
772
+ * ``t1``, ``p1``: Engle-Granger test statistic and p-value.
773
+ * ``t2``, ``p2``: Engle-Granger test statistic and p-value (alternate form).
774
+ * ``trace0``, ``trace1``: Johansen test trace statistics.
775
+ * ``k_ar_diff``: Selected lag order for the Johansen test.
770
776
 
771
777
  References
772
778
  ----------
773
- Stefan Jansen (2020). Machine Learning for Algorithmic Trading - Second Edition.
774
- chapter 9, Time-Series Models for Volatility Forecasts and Statistical Arbitrage.
779
+ * [1] Jansen, S. (2020). Machine Learning for Algorithmic Trading -
780
+ Second Edition. Packt Publishing. Chapter 9, Time-Series Models
781
+ for Volatility Forecasts and Statistical Arbitrage.
775
782
  """
776
783
  security = security.div(security.iloc[0])
777
784
  ticker = security.name
@@ -834,102 +841,65 @@ def find_cointegrated_pairs(
834
841
  such as cointegration and Engle-Granger significance, to determine pairs suitable
835
842
  for financial strategies like pairs trading.
836
843
 
837
- Args:
838
- securities (`pd.DataFrame`): A DataFrame where each column represents the time-series
839
- prices of target securities to evaluate.
840
- candidates (`pd.DataFrame`): A DataFrame where each column represents the time-series
841
- prices of candidate securities to compare against the target securities.
842
- n (`int`, optional): The number of top pairs to return. If `None`, returns all pairs.
843
- start (`str`, optional): Start date for slicing the data (e.g., 'YYYY-MM-DD').
844
- stop (`str`, optional): End date for slicing the data (e.g., 'YYYY-MM-DD').
845
- coint (`bool`, optional, default=False):
846
- - If `True`, filters for pairs identified as cointegrated.
847
- - If `False`, returns all evaluated pairs.
844
+ Parameters
845
+ ----------
846
+ securities : pd.DataFrame
847
+ A DataFrame where each column represents the time-series
848
+ prices of target securities to evaluate.
849
+ candidates : pd.DataFrame
850
+ A DataFrame where each column represents the time-series
851
+ prices of candidate securities to compare against the target securities.
852
+ n : int, optional
853
+ The number of top pairs to return. If ``None``, returns all pairs.
854
+ start : str, optional
855
+ Start date for slicing the data (e.g., 'YYYY-MM-DD').
856
+ stop : str, optional
857
+ End date for slicing the data (e.g., 'YYYY-MM-DD').
858
+ coint : bool, optional, default=False
859
+ If ``True``, filters for pairs identified as cointegrated.
860
+ If ``False``, returns all evaluated pairs.
861
+
862
+ Returns
863
+ -------
864
+ pd.DataFrame
865
+ A DataFrame containing:
866
+
867
+ **Johansen and Engle-Granger cointegration metrics**
868
+ * ``t1``, ``t2`` : Engle-Granger test statistics for two directions.
869
+ * ``p1``, ``p2`` : Engle-Granger p-values for two directions.
870
+ * ``trace0``, ``trace1`` : Johansen test trace statistics for 0 and 1 cointegration relationships.
871
+
872
+ **Indicators and filters**
873
+ * ``joh_sig`` : Indicates Johansen cointegration significance.
874
+ * ``eg_sig`` : Indicates Engle-Granger significance (p-value < 0.05).
875
+ * ``s1_dep`` : Indicates whether the first series depends on the second (based on p-values).
876
+ * ``coint`` : Combined cointegration indicator (Johansen & Engle-Granger).
877
+
878
+ **Spread and ranking**
879
+ * ``t`` : Minimum of ``t1`` and ``t2``.
880
+ * ``p`` : Minimum of ``p1`` and ``p2``.
848
881
 
849
- Returns:
850
- - ``pd.DataFrame``: A DataFrame containing:
851
- - Johansen and Engle-Granger cointegration metrics:
852
- - `t1`, `t2`: Engle-Granger test statistics for two directions.
853
- - `p1`, `p2`: Engle-Granger p-values for two directions.
854
- - `trace0`, `trace1`: Johansen test trace statistics for 0 and 1 cointegration relationships.
855
- - Indicators and filters:
856
- - `joh_sig`: Indicates Johansen cointegration significance.
857
- - `eg_sig`: Indicates Engle-Granger significance (p-value < 0.05).
858
- - `s1_dep`: Indicates whether the first series depends on the second (based on p-values).
859
- - `coint`: Combined cointegration indicator (Johansen & Engle-Granger).
860
- - Spread and ranking:
861
- - `t`: Minimum of `t1` and `t2`.
862
- - `p`: Minimum of `p1` and `p2`.
863
882
  References
864
883
  ----------
865
- Stefan Jansen (2020). Machine Learning for Algorithmic Trading - Second Edition.
866
- chapter 9, Time-Series Models for Volatility Forecasts and Statistical Arbitrage.
867
-
868
- Example:
869
- >>> import pandas as pd
884
+ Stefan Jansen (2020). *Machine Learning for Algorithmic Trading - Second Edition*.
885
+ Chapter 9, Time-Series Models for Volatility Forecasts and Statistical Arbitrage.
870
886
 
871
- >>> # Sample Data
872
- >>> data_securities = {
873
- ... 'Security1': [100, 102, 101, 103, 105],
874
- ... 'Security2': [50, 52, 53, 51, 54]
875
- ... }
876
- >>> data_candidates = {
877
- ... 'Candidate1': [100, 101, 99, 102, 104],
878
- ... 'Candidate2': [200, 202, 201, 203, 205]
879
- ... }
880
-
881
- >>> securities = pd.DataFrame(data_securities, index=pd.date_range('2023-01-01', periods=5))
882
- >>> candidates = pd.DataFrame(data_candidates, index=pd.date_range('2023-01-01', periods=5))
883
-
884
- >>> # Find cointegrated pairs
885
- >>> top_pairs = find_cointegrated_pairs(securities, candidates, n=2, coint=True)
886
- >>> print(top_pairs)
887
-
888
- >>> | s1 | s2 | t | p | joh_sig | eg_sig | coint |
889
- >>> |----------|-----------|------|-------|---------|--------|-------|
890
- >>> | Security1| Candidate1| -3.5 | 0.01 | 1 | 1 | 1 |
891
- >>> | Security2| Candidate2| -2.9 | 0.04 | 1 | 1 | 1 |
887
+ Examples
888
+ --------
889
+ >>> import pandas as pd
890
+ >>> data_securities = {
891
+ ... 'Security1': [100, 102, 101, 103, 105],
892
+ ... 'Security2': [50, 52, 53, 51, 54]
893
+ ... }
894
+ >>> data_candidates = {
895
+ ... 'Candidate1': [100, 101, 99, 102, 104],
896
+ ... 'Candidate2': [200, 202, 201, 203, 205]
897
+ ... }
898
+ >>> securities = pd.DataFrame(data_securities, index=pd.date_range('2023-01-01', periods=5))
899
+ >>> candidates = pd.DataFrame(data_candidates, index=pd.date_range('2023-01-01', periods=5))
900
+ >>> top_pairs = find_cointegrated_pairs(securities, candidates, n=2, coint=True)
901
+ >>> print(top_pairs)
892
902
  """
893
- trace0_cv = __CRITICAL_VALUES[0][
894
- 0.95
895
- ] # critical value for 0 cointegration relationships
896
- # critical value for 1 cointegration relationship
897
- trace1_cv = __CRITICAL_VALUES[1][0.95]
898
- spreads = []
899
- if start is not None and stop is not None:
900
- securities = securities.loc[str(start) : str(stop), :]
901
- candidates = candidates.loc[str(start) : str(stop), :]
902
- for i, (ticker, prices) in enumerate(securities.items(), 1):
903
- try:
904
- df = compute_pair_metrics(prices, candidates)
905
- spreads.append(df.set_index("s1", append=True))
906
- except np.linalg.LinAlgError:
907
- continue
908
- spreads = pd.concat(spreads)
909
- spreads.index.names = ["s2", "s1"]
910
- spreads = spreads.swaplevel()
911
- spreads["t"] = spreads[["t1", "t2"]].min(axis=1)
912
- spreads["p"] = spreads[["p1", "p2"]].min(axis=1)
913
- spreads["joh_sig"] = (
914
- (spreads.trace0 > trace0_cv) & (spreads.trace1 > trace1_cv)
915
- ).astype(int)
916
- spreads["eg_sig"] = (spreads.p < 0.05).astype(int)
917
- spreads["s1_dep"] = spreads.p1 < spreads.p2
918
- spreads["coint"] = (spreads.joh_sig & spreads.eg_sig).astype(int)
919
- # select top n pairs
920
- if coint:
921
- if n is not None:
922
- top_pairs = (
923
- spreads.query("coint == 1").sort_values("t", ascending=False).head(n)
924
- )
925
- else:
926
- top_pairs = spreads.query("coint == 1").sort_values("t", ascending=False)
927
- else:
928
- if n is not None:
929
- top_pairs = spreads.sort_values("t", ascending=False).head(n)
930
- else:
931
- top_pairs = spreads.sort_values("t", ascending=False)
932
- return top_pairs
933
903
 
934
904
 
935
905
  def analyze_cointegrated_pairs(
@@ -1121,25 +1091,31 @@ def KFSmoother(prices: pd.Series | np.ndarray) -> pd.Series | np.ndarray:
1121
1091
 
1122
1092
 
1123
1093
  def KFHedgeRatio(x: pd.Series | np.ndarray, y: pd.Series | np.ndarray) -> np.ndarray:
1124
- """
1125
- Estimate Hedge Ratio using Kalman Filter.
1126
- Args:
1127
- x : pd.Series or np.ndarray
1128
- The independent variable, which can be either a pandas Series or a numpy array.
1129
- y : pd.Series or np.ndarray
1130
- The dependent variable, which can be either a pandas Series or a numpy array.
1094
+ """Estimate Hedge Ratio using Kalman Filter.
1131
1095
 
1132
- Returns:
1133
- np.ndarray
1134
- The estimated hedge ratio as a numpy array.
1096
+ This function uses a Kalman Filter to dynamically estimate the hedge ratio
1097
+ (beta) and intercept (alpha) for a pair of assets over time.
1135
1098
 
1136
- The function returns the negative of the first state variable of each Kalman Filter estimate,
1137
- which represents the estimated hedge ratio.
1099
+ The function returns the negative of the first state variable (the hedge ratio)
1100
+ for each time step, which is a common convention in pairs trading.
1101
+
1102
+ Parameters
1103
+ ----------
1104
+ x : pd.Series or np.ndarray
1105
+ The independent variable (e.g., price series of asset X).
1106
+ y : pd.Series or np.ndarray
1107
+ The dependent variable (e.g., price series of asset Y).
1108
+
1109
+ Returns
1110
+ -------
1111
+ np.ndarray
1112
+ The time-varying estimated hedge ratio as a numpy array.
1138
1113
 
1139
1114
  References
1140
1115
  ----------
1141
- Stefan Jansen (2020). Machine Learning for Algorithmic Trading - Second Edition.
1142
- chapter 9, Time-Series Models for Volatility Forecasts and Statistical Arbitrage.
1116
+ * [1] Jansen, S. (2020). Machine Learning for Algorithmic Trading -
1117
+ Second Edition. Packt Publishing. Chapter 9, Time-Series Models
1118
+ for Volatility Forecasts and Statistical Arbitrage.
1143
1119
  """
1144
1120
  if not isinstance(x, (np.ndarray, pd.Series)) or not isinstance(
1145
1121
  y, (np.ndarray, pd.Series)
@@ -1,13 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bbstrader
3
- Version: 0.3.5
3
+ Version: 0.3.6
4
4
  Summary: Simplified Investment & Trading Toolkit
5
- Home-page: https://github.com/bbalouki/bbstrader
6
- Download-URL: https://pypi.org/project/bbstrader/
7
- Author: Bertin Balouki SIMYELI
8
- Author-email: <bertin@bbstrader.com>
9
- Maintainer: Bertin Balouki SIMYELI
10
- License: MIT
5
+ Author-email: Bertin Balouki SIMYELI <bertin@bbstrader.com>
6
+ Maintainer-email: Bertin Balouki SIMYELI <bertin@bbstrader.com>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/bbalouki/bbstrader
9
+ Project-URL: Download, https://pypi.org/project/bbstrader/
11
10
  Project-URL: Documentation, https://bbstrader.readthedocs.io/en/latest/
12
11
  Project-URL: Source Code, https://github.com/bbalouki/bbstrader
13
12
  Keywords: Finance,Toolkit,Financial,Analysis,Fundamental,Quantitative,Database,Equities,Currencies,Economics,ETFs,Funds,Indices,Moneymarkets,Commodities,Futures,CFDs,Derivatives,Trading,Investing,Portfolio,Optimization,Performance
@@ -19,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.12
19
18
  Classifier: Operating System :: Microsoft :: Windows
20
19
  Classifier: Operating System :: POSIX :: Linux
21
20
  Classifier: Operating System :: MacOS
21
+ Requires-Python: >=3.12
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE
24
24
  Requires-Dist: alphalens-reloaded>=0.4.6
@@ -58,21 +58,7 @@ Requires-Dist: vaderSentiment>=3.3.2
58
58
  Requires-Dist: yfinance>=0.2.65
59
59
  Provides-Extra: mt5
60
60
  Requires-Dist: MetaTrader5; extra == "mt5"
61
- Dynamic: author
62
- Dynamic: author-email
63
- Dynamic: classifier
64
- Dynamic: description
65
- Dynamic: description-content-type
66
- Dynamic: download-url
67
- Dynamic: home-page
68
- Dynamic: keywords
69
- Dynamic: license
70
61
  Dynamic: license-file
71
- Dynamic: maintainer
72
- Dynamic: project-url
73
- Dynamic: provides-extra
74
- Dynamic: requires-dist
75
- Dynamic: summary
76
62
 
77
63
  # Simplified Investment & Trading Toolkit
78
64
  [![Documentation Status](https://readthedocs.org/projects/bbstrader/badge/?version=latest)](https://bbstrader.readthedocs.io/en/latest/?badge=latest)
@@ -1,10 +1,10 @@
1
- bbstrader/__init__.py,sha256=-5f30lprSg-ufbPbmj1J3P63elB--NPXo9_G_QuhWF0,581
2
- bbstrader/__main__.py,sha256=RjUIJWaD2_Od8ZMSLL8dzc2ZuCkkzlvNaE7-LIu3RGU,2488
1
+ bbstrader/__init__.py,sha256=kUjCDqDwFaqgcJkaLrgRGiaTwyxG3iTTbOy8V3iefYk,747
2
+ bbstrader/__main__.py,sha256=Cc3cSqHSCOdhk6gsg0lfL5TOaNz_ODXoe1wWgr_DewQ,2745
3
3
  bbstrader/compat.py,sha256=bHTPTalffQNVv7MNRPaimJ4d9rQEwQFLSovHlUbxNgA,647
4
4
  bbstrader/config.py,sha256=Q8xi6laFo-R-NNGotbHOgy8GLLuwvH6MaoiLhfTbYok,3548
5
- bbstrader/tseries.py,sha256=SM_LTQHJ3ZXVkVJyZ51CefUDzJDl2TkJqBKMp_uM8s4,43833
5
+ bbstrader/tseries.py,sha256=fEIsG0kkMuG1TSrMnPK1u-tihzfFIOR675s18p3pg4A,41953
6
6
  bbstrader/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- bbstrader/apps/_copier.py,sha256=z6GhLSmFjHc_oh7pYRTflH42Xmpe3Z7B2fUyedzDQPo,25387
7
+ bbstrader/apps/_copier.py,sha256=wI33uEKEw8WElb4QA34UBbsXl4o7OqpjPSV023n_bb8,25393
8
8
  bbstrader/btengine/__init__.py,sha256=y1btjaEfhWsH8vuE7mBRpP9Tu-Azt9REhuVYsPCAfBU,2955
9
9
  bbstrader/btengine/backtest.py,sha256=o3eoCVzpjykDx-9VgkxK6DKZdGDAuLVeeWLCa2U_zeY,14652
10
10
  bbstrader/btengine/data.py,sha256=WcBLtabboZkQdtOQS3SjbiJD9BcWc75sdhZ2voQ_lUw,27061
@@ -13,7 +13,7 @@ bbstrader/btengine/execution.py,sha256=4MytWjcKg8J_w14P43emHqsvKOElkQTfhVYNakU6e
13
13
  bbstrader/btengine/performance.py,sha256=1ecWrTzHBQbk4ORvbTEKxwCzlL1brcXOEUwgbnjAwx4,12470
14
14
  bbstrader/btengine/portfolio.py,sha256=z98M65HQeCyma8gMZkAxspxBA9jtIhzxMyJUHPPj34c,16128
15
15
  bbstrader/btengine/scripts.py,sha256=8o66dq4Ex4DsH4s8xvJqUOFjLzZJSnbBvvNBzohtzoE,4837
16
- bbstrader/btengine/strategy.py,sha256=hDghr5sXNitWlWXXvgl8Vj-QHWaIuVlx54LUXAbQrHQ,36725
16
+ bbstrader/btengine/strategy.py,sha256=6MR2atgXA4bkMQ9TE1lPr6P8vKAUoT0YoLmOFYEJiaA,39242
17
17
  bbstrader/core/__init__.py,sha256=GIFzFSStPfE0XM2j7mDeZZQeMTh_AwPsDOQXwMVJLgw,97
18
18
  bbstrader/core/data.py,sha256=5-ByClb-E3-iqDz8CBJ4om9wBIA7DmUWezu4A-tv5ys,25095
19
19
  bbstrader/core/scripts.py,sha256=7lNddfX7WaZfiE5dENEfzv3XrAPrwoE9FYSaTie3cwM,5524
@@ -21,29 +21,42 @@ bbstrader/core/utils.py,sha256=tHXQimmmlYZHktNnYNKn_wVq6v-85pI7DXF6xlJV7ps,2780
21
21
  bbstrader/ibkr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  bbstrader/ibkr/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  bbstrader/metatrader/__init__.py,sha256=A5Ye9tpc2sp9Xk5qjKw-EfYsoRcZtAt8nqvC3tCtZs8,333
24
- bbstrader/metatrader/account.py,sha256=Ur0vKz_puUP9jmdJUpvdQq6W5ue0RfnhkL0JLPBQkOE,65200
25
- bbstrader/metatrader/analysis.py,sha256=ywETmG3qxZ7ms_DCjR1GcQoUrQ0es5-n-CPDYKBAm8Q,3614
26
- bbstrader/metatrader/copier.py,sha256=RxXm_NKpaad4sMT1kuJNjeJcbP368asXLaAVqmoRfmE,55553
24
+ bbstrader/metatrader/account.py,sha256=5YdvRggBxfZ6MQX70EFfwAZ7tuHvGzkwyEw1GgtiR4c,65501
25
+ bbstrader/metatrader/analysis.py,sha256=HuxYiKwa7VYmI_noqc4OAKSoC7bJpYm-OosQGZdMEnU,3694
26
+ bbstrader/metatrader/copier.py,sha256=VOo0RfuNoItc10CRGdX8MsUtcBBAzoY42sfolmvgptg,56052
27
27
  bbstrader/metatrader/rates.py,sha256=w9mr6FB6E1zLcHCDtDGt-oMnw6sakIU6Qe3455KDsSg,20782
28
28
  bbstrader/metatrader/risk.py,sha256=NhW8qtSg350Z6H9oLcDqOU_erqd_7Y7F5FwpfPN5Qso,27262
29
29
  bbstrader/metatrader/scripts.py,sha256=8meq6_zz6jPSibNgtYtaO8Ba-uJZOoLkpqYUIjidk-U,4010
30
- bbstrader/metatrader/trade.py,sha256=X6DNpPrHL0xQUAblJsCxmpSNWlFw8otEM1pWpgYTydE,81041
31
- bbstrader/metatrader/utils.py,sha256=PnFZ8EuBSZgsYlvwZDOxj4vUTtt-hUYnnwFBmu7gxxw,20738
30
+ bbstrader/metatrader/trade.py,sha256=-tMbMBSTGAFJe9xK706uhR0Na8lJu7vfEhmud9Q3XnU,81003
31
+ bbstrader/metatrader/utils.py,sha256=Yt3mx8EgS6u1-irQG6uQn-LhC3kyWOVE00VepnDAtCI,20802
32
32
  bbstrader/models/__init__.py,sha256=B-bn2h_SCK6gRAs2li6dDVnvV8jDT5suZimldk5xxcw,497
33
33
  bbstrader/models/factors.py,sha256=J7yxtDr1sCTw1AI59kluF89e2b9HkpEXfFyIcfPHUCQ,13008
34
34
  bbstrader/models/ml.py,sha256=NVN9zxRRDJn2S8KSgGBkiSHvdFjsDiaNsW2Y6rs51Io,50314
35
- bbstrader/models/nlp.py,sha256=hcvz9d_8j1cIC1h3oqa1DBjExRIEd6WSiZb95Vr3NPo,32638
35
+ bbstrader/models/nlp.py,sha256=z_mbL58U5UGXc7ocVtvUR_zUYSk7Om2Gu7xXYBerxQY,32619
36
36
  bbstrader/models/optimization.py,sha256=Fa4tdhynMmvKt5KHV9cH1TXmmJVJwU4QWpYkbeVq4aI,6395
37
37
  bbstrader/models/portfolio.py,sha256=r-47Zrn2r7iKCHm5YVtwkbBJXAZGM3QYy-rXCWY9-Bg,8079
38
38
  bbstrader/models/risk.py,sha256=MKCk53HtGIcivrNzH8Ikm5KMs1rXhFT5zkorUf30PyQ,506
39
39
  bbstrader/trading/__init__.py,sha256=ycLyuuxN5SujqtzR9X0Q74UQfK93q2va-GGAXdr-KS8,457
40
- bbstrader/trading/execution.py,sha256=CYt4fageoqcpMFvdRH-jX4hexAGUiG_wE94i1qg7BFM,41479
40
+ bbstrader/trading/execution.py,sha256=CPjOKvVFq8ZnANQrOtpakp64ZAhn-73Bu-D9UPCKUws,41832
41
41
  bbstrader/trading/scripts.py,sha256=Tf5q33WqqygjpIv43_8nA82VZ3GM0qgb4Ggo3fHJ_wg,5744
42
42
  bbstrader/trading/strategies.py,sha256=RZ6P4SfIyRW72v0OnPnrc4Hv8X00FdxR-_sD23xe_Pg,11756
43
43
  bbstrader/trading/utils.py,sha256=57dKF9dcRu04oU2VRqydRrzW39dCW2wlDWhVt-sZdRw,1857
44
- bbstrader-0.3.5.dist-info/licenses/LICENSE,sha256=ZwC_RqqGmOPBUiMDKqLyJZ5HBeHq53LpL7TMRzrJY8c,1094
45
- bbstrader-0.3.5.dist-info/METADATA,sha256=-FeMRpGJTL9HvVnWmNbhLiHlu0kYfb7wqqANfLzVrew,26910
46
- bbstrader-0.3.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
- bbstrader-0.3.5.dist-info/entry_points.txt,sha256=0yDCbhbgHswOzJnY5wRSM_FjjyMHGvY7lJpSSVh0xtI,54
48
- bbstrader-0.3.5.dist-info/top_level.txt,sha256=Wwj322jZmxGZ6gD_TdaPiPLjED5ReObm5omerwlmZIg,10
49
- bbstrader-0.3.5.dist-info/RECORD,,
44
+ bbstrader-0.3.6.dist-info/licenses/LICENSE,sha256=ZwC_RqqGmOPBUiMDKqLyJZ5HBeHq53LpL7TMRzrJY8c,1094
45
+ docs/conf.py,sha256=q_Z8_iz-YDgHhe4PpCOAtvN5Q-2hHquliG07FDEXdjo,1686
46
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
+ tests/engine/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
48
+ tests/engine/test_backtest.py,sha256=OmHimBp518BBv0Eg-t_cIrBXMzfiYOGki5FW7kqFeFs,2136
49
+ tests/engine/test_data.py,sha256=jAVICMt4YTKF5PN6ZIxhQ9CuUjbw9_gIPAC4sNA9GsE,19907
50
+ tests/engine/test_events.py,sha256=is3v3mtQVKFVNyn-xF4F7yuBGA5vqgunqsoFgNJeH0c,11755
51
+ tests/engine/test_execution.py,sha256=Sk3d_Rl9T0GjArficd75hEeVyeB_7yOcTD8ltpN4UlY,7961
52
+ tests/engine/test_portfolio.py,sha256=csKWO4W0xWn3obxuPRBFAUHHR60j-IZfAz5bv7Y_u9M,9872
53
+ tests/metatrader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
+ tests/metatrader/test_account.py,sha256=UiAWP0IRd6a1kmA_pTcEuCZAJjtq0U_Q-PcOdd2l69A,68627
55
+ tests/metatrader/test_rates.py,sha256=dc43jAvkZby9TMJcwkcaEvH21jQudk1D8KQxWLlAYoQ,10424
56
+ tests/metatrader/test_risk_management.py,sha256=lMT0m7dmT3iWihTkEwpMoHdJPPWU3XJmqgCV4qKT-uw,31019
57
+ tests/metatrader/test_trade.py,sha256=gMyinOOgVC2SOV8xLMIKqUTwqXbSUuDGnhSmspXK9cw,15177
58
+ bbstrader-0.3.6.dist-info/METADATA,sha256=zPS1ez6FJWRlX70OAjC9tSNerd1GuQJP9Hxv4mzorgc,26693
59
+ bbstrader-0.3.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
60
+ bbstrader-0.3.6.dist-info/entry_points.txt,sha256=0yDCbhbgHswOzJnY5wRSM_FjjyMHGvY7lJpSSVh0xtI,54
61
+ bbstrader-0.3.6.dist-info/top_level.txt,sha256=raTnmqZJ2B3Mvrhy_fV9szurE9yVctrKHBLZ1NJ5vnU,21
62
+ bbstrader-0.3.6.dist-info/RECORD,,
@@ -0,0 +1,3 @@
1
+ bbstrader
2
+ docs
3
+ tests
docs/conf.py ADDED
@@ -0,0 +1,56 @@
1
+ # Configuration file for the Sphinx documentation builder.
2
+ #
3
+ # For the full list of built-in configuration values, see the documentation:
4
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html
5
+
6
+ # -- Project information -----------------------------------------------------
7
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
8
+ import os
9
+ import sys
10
+ from unittest.mock import MagicMock
11
+ from importlib.metadata import version, PackageNotFoundError
12
+
13
+ os.system('pip install ..')
14
+ sys.path.insert(0, os.path.abspath('../bbstrader'))
15
+
16
+ class Mock(MagicMock):
17
+ @classmethod
18
+ def __getattr__(cls, name):
19
+ return MagicMock()
20
+
21
+ # List the mock modules to avoid import errors
22
+ MOCK_MODULES = ['MetaTrader5', 'talib', 'posix']
23
+ sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)
24
+
25
+ project = 'bbstrader'
26
+ copyright = '2023 - 2025, Bertin Balouki SIMYELI'
27
+ author = 'Bertin Balouki SIMYELI'
28
+
29
+ try:
30
+ release = version("bbstrader")
31
+ except PackageNotFoundError:
32
+ release = "unknown"
33
+ version = ".".join(release.split('.')[:2])
34
+
35
+ # -- General configuration ---------------------------------------------------
36
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
37
+
38
+
39
+ extensions = [
40
+ 'sphinx.ext.autodoc',
41
+ 'sphinx.ext.napoleon',
42
+ 'sphinx.ext.viewcode',
43
+ 'sphinx.ext.todo',
44
+ ]
45
+
46
+
47
+ templates_path = ['_templates']
48
+ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
49
+
50
+
51
+
52
+ # -- Options for HTML output -------------------------------------------------
53
+ # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
54
+
55
+ html_theme = 'sphinx_rtd_theme'
56
+ html_static_path = ['_static']
tests/__init__.py ADDED
File without changes
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,58 @@
1
+ import unittest
2
+ from unittest.mock import MagicMock
3
+ from datetime import datetime
4
+ from bbstrader.btengine.backtest import BacktestEngine
5
+
6
+
7
+ class TestBacktestEngine(unittest.TestCase):
8
+ def setUp(self):
9
+ # Create mock classes with minimum expected interface
10
+ self.symbol_list = ['FAKE']
11
+ self.initial_capital = 100000.0
12
+ self.heartbeat = 0.0
13
+ self.start_date = datetime(2020, 1, 1)
14
+
15
+ self.mock_data_handler_cls = MagicMock()
16
+ self.mock_strategy_cls = MagicMock()
17
+ self.mock_execution_handler_cls = MagicMock()
18
+
19
+ # Mock data_handler instance
20
+ self.mock_data_handler = MagicMock()
21
+ self.mock_data_handler.continue_backtest = False
22
+ self.mock_data_handler.get_latest_bar_datetime.return_value = self.start_date
23
+ self.mock_data_handler.update_bars.return_value = None
24
+
25
+ # Strategy and portfolio mock
26
+ self.mock_strategy = MagicMock()
27
+ self.mock_strategy.check_pending_orders.return_value = None
28
+ self.mock_strategy.get_update_from_portfolio.return_value = None
29
+
30
+ self.mock_portfolio = MagicMock()
31
+ self.mock_portfolio.all_holdings = [{"Total": self.initial_capital}]
32
+ self.mock_portfolio.current_positions = {}
33
+ self.mock_portfolio.current_holdings = {}
34
+
35
+ self.mock_execution_handler = MagicMock()
36
+
37
+ # Bind mock return values
38
+ self.mock_data_handler_cls.return_value = self.mock_data_handler
39
+ self.mock_strategy_cls.return_value = self.mock_strategy
40
+ self.mock_execution_handler_cls.return_value = self.mock_execution_handler
41
+
42
+ def test_backtest_engine_runs(self):
43
+ engine = BacktestEngine(
44
+ self.symbol_list,
45
+ self.initial_capital,
46
+ self.heartbeat,
47
+ self.start_date,
48
+ self.mock_data_handler_cls,
49
+ self.mock_execution_handler_cls,
50
+ self.mock_strategy_cls,
51
+ )
52
+ engine.portfolio = self.mock_portfolio
53
+
54
+ result = engine.simulate_trading()
55
+ self.assertTrue(hasattr(result, '__class__'))
56
+
57
+ if __name__ == "__main__":
58
+ unittest.main()