bbstrader 0.3.6__py3-none-any.whl → 0.3.7__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/__init__.py +1 -1
- bbstrader/__main__.py +2 -2
- bbstrader/apps/_copier.py +40 -37
- bbstrader/btengine/backtest.py +33 -28
- bbstrader/btengine/data.py +105 -81
- bbstrader/btengine/event.py +21 -22
- bbstrader/btengine/execution.py +51 -24
- bbstrader/btengine/performance.py +23 -12
- bbstrader/btengine/portfolio.py +40 -30
- bbstrader/btengine/scripts.py +13 -12
- bbstrader/btengine/strategy.py +288 -101
- bbstrader/compat.py +4 -3
- bbstrader/config.py +20 -36
- bbstrader/core/data.py +76 -48
- bbstrader/core/scripts.py +22 -21
- bbstrader/core/utils.py +13 -12
- bbstrader/trading/execution.py +6 -0
- bbstrader/tseries.py +55 -39
- {bbstrader-0.3.6.dist-info → bbstrader-0.3.7.dist-info}/METADATA +3 -3
- {bbstrader-0.3.6.dist-info → bbstrader-0.3.7.dist-info}/RECORD +25 -25
- tests/engine/test_portfolio.py +3 -2
- {bbstrader-0.3.6.dist-info → bbstrader-0.3.7.dist-info}/WHEEL +0 -0
- {bbstrader-0.3.6.dist-info → bbstrader-0.3.7.dist-info}/entry_points.txt +0 -0
- {bbstrader-0.3.6.dist-info → bbstrader-0.3.7.dist-info}/licenses/LICENSE +0 -0
- {bbstrader-0.3.6.dist-info → bbstrader-0.3.7.dist-info}/top_level.txt +0 -0
bbstrader/tseries.py
CHANGED
|
@@ -5,7 +5,7 @@ some simple time series analysis in financial markets.
|
|
|
5
5
|
|
|
6
6
|
import pprint
|
|
7
7
|
import warnings
|
|
8
|
-
from typing import List, Tuple, Union
|
|
8
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
9
9
|
|
|
10
10
|
import matplotlib.pyplot as plt
|
|
11
11
|
import numpy as np
|
|
@@ -94,7 +94,7 @@ def get_corr(tickers: Union[List[str], Tuple[str, ...]], start: str, end: str) -
|
|
|
94
94
|
)
|
|
95
95
|
|
|
96
96
|
|
|
97
|
-
def plot_price_series(df: pd.DataFrame, ts1: str, ts2: str):
|
|
97
|
+
def plot_price_series(df: pd.DataFrame, ts1: str, ts2: str) -> None:
|
|
98
98
|
"""
|
|
99
99
|
Plot both time series on the same line graph for
|
|
100
100
|
the specified date range.
|
|
@@ -117,7 +117,7 @@ def plot_price_series(df: pd.DataFrame, ts1: str, ts2: str):
|
|
|
117
117
|
plt.show()
|
|
118
118
|
|
|
119
119
|
|
|
120
|
-
def plot_scatter_series(df: pd.DataFrame, ts1: str, ts2: str):
|
|
120
|
+
def plot_scatter_series(df: pd.DataFrame, ts1: str, ts2: str) -> None:
|
|
121
121
|
"""
|
|
122
122
|
Plot a scatter plot of both time series for
|
|
123
123
|
via the provided DataFrame.
|
|
@@ -146,7 +146,7 @@ def plot_scatter_series(df: pd.DataFrame, ts1: str, ts2: str):
|
|
|
146
146
|
plt.show()
|
|
147
147
|
|
|
148
148
|
|
|
149
|
-
def plot_residuals(df: pd.DataFrame):
|
|
149
|
+
def plot_residuals(df: pd.DataFrame) -> None:
|
|
150
150
|
"""
|
|
151
151
|
Plot the residuals of OLS procedure for both
|
|
152
152
|
time series.
|
|
@@ -299,7 +299,7 @@ def run_hurst_test(symbol: str, start: str, end: str):
|
|
|
299
299
|
)
|
|
300
300
|
|
|
301
301
|
|
|
302
|
-
def test_cointegration(ticker1, ticker2, start, end):
|
|
302
|
+
def test_cointegration(ticker1: str, ticker2: str, start: str, end: str) -> None:
|
|
303
303
|
warnings.warn(
|
|
304
304
|
"`test_cointegration` is deprecated, see statsmodels.tsa.stattools.coint instead.",
|
|
305
305
|
DeprecationWarning,
|
|
@@ -307,13 +307,15 @@ def test_cointegration(ticker1, ticker2, start, end):
|
|
|
307
307
|
|
|
308
308
|
|
|
309
309
|
def run_coint_test(tickers: List[str], start: str, end: str) -> None:
|
|
310
|
-
test_cointegration()
|
|
310
|
+
test_cointegration(tickers[0], tickers[1], start, end)
|
|
311
311
|
|
|
312
312
|
|
|
313
313
|
# *********************************
|
|
314
314
|
# KALMAN FILTER *
|
|
315
315
|
# *********************************
|
|
316
|
-
def draw_date_coloured_scatterplot(
|
|
316
|
+
def draw_date_coloured_scatterplot(
|
|
317
|
+
etfs: Union[List[str], Tuple[str, ...]], prices: pd.DataFrame
|
|
318
|
+
) -> None:
|
|
317
319
|
"""
|
|
318
320
|
Create a scatterplot of the two ETF prices, which is
|
|
319
321
|
coloured by the date of the price to indicate the
|
|
@@ -341,7 +343,9 @@ def draw_date_coloured_scatterplot(etfs, prices):
|
|
|
341
343
|
plt.show()
|
|
342
344
|
|
|
343
345
|
|
|
344
|
-
def calc_slope_intercept_kalman(
|
|
346
|
+
def calc_slope_intercept_kalman(
|
|
347
|
+
etfs: Union[List[str], Tuple[str, ...]], prices: pd.DataFrame
|
|
348
|
+
) -> Tuple[np.ndarray, np.ndarray]:
|
|
345
349
|
"""
|
|
346
350
|
Utilize the Kalman Filter from the filterpy library
|
|
347
351
|
to calculate the slope and intercept of the regressed
|
|
@@ -371,7 +375,7 @@ def calc_slope_intercept_kalman(etfs, prices):
|
|
|
371
375
|
return np.array(state_means), np.array(state_covs)
|
|
372
376
|
|
|
373
377
|
|
|
374
|
-
def draw_slope_intercept_changes(prices, state_means):
|
|
378
|
+
def draw_slope_intercept_changes(prices: pd.DataFrame, state_means: np.ndarray) -> None:
|
|
375
379
|
"""
|
|
376
380
|
Plot the slope and intercept of the regressed ETF prices
|
|
377
381
|
between the two ETFs, with the changing values of the
|
|
@@ -438,7 +442,9 @@ class KalmanFilterModel:
|
|
|
438
442
|
You can learn more here https://en.wikipedia.org/wiki/Kalman_filter
|
|
439
443
|
"""
|
|
440
444
|
|
|
441
|
-
def __init__(
|
|
445
|
+
def __init__(
|
|
446
|
+
self, tickers: Union[List[str], Tuple[str, ...]], **kwargs: Any
|
|
447
|
+
) -> None:
|
|
442
448
|
"""
|
|
443
449
|
Initializes the Kalman Filter strategy.
|
|
444
450
|
|
|
@@ -452,7 +458,8 @@ class KalmanFilterModel:
|
|
|
452
458
|
self.tickers = tickers
|
|
453
459
|
assert self.tickers is not None
|
|
454
460
|
|
|
455
|
-
self.R = None
|
|
461
|
+
self.R: Optional[np.ndarray] = None
|
|
462
|
+
self.C: Optional[np.ndarray] = None
|
|
456
463
|
self.theta = np.zeros(2)
|
|
457
464
|
self.P = np.zeros((2, 2))
|
|
458
465
|
self.delta = kwargs.get("delta", 1e-4)
|
|
@@ -461,7 +468,7 @@ class KalmanFilterModel:
|
|
|
461
468
|
self.latest_prices = np.array([-1.0, -1.0])
|
|
462
469
|
self.kf = self._init_kalman()
|
|
463
470
|
|
|
464
|
-
def _init_kalman(self):
|
|
471
|
+
def _init_kalman(self) -> KalmanFilter:
|
|
465
472
|
"""
|
|
466
473
|
Initializes and returns a Kalman Filter configured
|
|
467
474
|
for the trading strategy. The filter is set up with initial
|
|
@@ -477,9 +484,7 @@ class KalmanFilterModel:
|
|
|
477
484
|
|
|
478
485
|
return kf
|
|
479
486
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
def calc_slope_intercep(self, prices: Array) -> Tuple:
|
|
487
|
+
def calc_slope_intercep(self, prices: np.ndarray) -> Tuple[float, float]:
|
|
483
488
|
"""
|
|
484
489
|
Calculates and returns the slope and intercept
|
|
485
490
|
of the relationship between the provided prices using the Kalman Filter.
|
|
@@ -500,7 +505,7 @@ class KalmanFilterModel:
|
|
|
500
505
|
|
|
501
506
|
return slope, intercept
|
|
502
507
|
|
|
503
|
-
def calculate_etqt(self, prices:
|
|
508
|
+
def calculate_etqt(self, prices: np.ndarray) -> Optional[Tuple[float, float]]:
|
|
504
509
|
"""
|
|
505
510
|
Calculates the ``forecast error`` and ``standard deviation`` of the predictions
|
|
506
511
|
using the Kalman Filter.
|
|
@@ -530,7 +535,7 @@ class KalmanFilterModel:
|
|
|
530
535
|
# The prior value of the states {\theta_t} is
|
|
531
536
|
# distributed as a multivariate Gaussian with
|
|
532
537
|
# mean a_t and variance-covariance {R_t}
|
|
533
|
-
if self.R is not None:
|
|
538
|
+
if self.R is not None and self.C is not None:
|
|
534
539
|
self.R = self.C + self.wt
|
|
535
540
|
else:
|
|
536
541
|
self.R = np.zeros((2, 2))
|
|
@@ -554,7 +559,7 @@ class KalmanFilterModel:
|
|
|
554
559
|
At = self.R.dot(F.T) / Qt
|
|
555
560
|
self.theta = self.theta + At.flatten() * et
|
|
556
561
|
self.C = self.R - At * F.dot(self.R)
|
|
557
|
-
return (et
|
|
562
|
+
return (et, sqrt_Qt.flatten()[0])
|
|
558
563
|
else:
|
|
559
564
|
return None
|
|
560
565
|
|
|
@@ -567,7 +572,7 @@ class OrnsteinUhlenbeck:
|
|
|
567
572
|
)
|
|
568
573
|
|
|
569
574
|
|
|
570
|
-
def remove_correlated_assets(df: pd.DataFrame, cutoff=0.99):
|
|
575
|
+
def remove_correlated_assets(df: pd.DataFrame, cutoff: float = 0.99) -> pd.DataFrame:
|
|
571
576
|
"""
|
|
572
577
|
Removes highly correlated assets from a DataFrame based on a specified correlation cutoff threshold.
|
|
573
578
|
This is useful in financial data analysis to reduce redundancy and multicollinearity in portfolios or datasets.
|
|
@@ -612,7 +617,7 @@ def remove_correlated_assets(df: pd.DataFrame, cutoff=0.99):
|
|
|
612
617
|
return df.drop(drop, axis=1)
|
|
613
618
|
|
|
614
619
|
|
|
615
|
-
def check_stationarity(df: pd.DataFrame):
|
|
620
|
+
def check_stationarity(df: pd.DataFrame) -> pd.DataFrame:
|
|
616
621
|
"""
|
|
617
622
|
Tests the stationarity of time-series data for each asset in the DataFrame
|
|
618
623
|
using the Augmented Dickey-Fuller (ADF) test. Stationarity is a key property
|
|
@@ -645,7 +650,7 @@ def check_stationarity(df: pd.DataFrame):
|
|
|
645
650
|
return pd.DataFrame(results, columns=["ticker", "adf"]).sort_values("adf")
|
|
646
651
|
|
|
647
652
|
|
|
648
|
-
def remove_stationary_assets(df: pd.DataFrame, pval=0.05):
|
|
653
|
+
def remove_stationary_assets(df: pd.DataFrame, pval: float = 0.05) -> pd.DataFrame:
|
|
649
654
|
"""
|
|
650
655
|
Filters out stationary assets from the DataFrame based on the p-value obtained
|
|
651
656
|
from the Augmented Dickey-Fuller test.
|
|
@@ -677,7 +682,13 @@ def remove_stationary_assets(df: pd.DataFrame, pval=0.05):
|
|
|
677
682
|
return df.drop(stationary, axis=1).sort_index()
|
|
678
683
|
|
|
679
684
|
|
|
680
|
-
def select_assets(
|
|
685
|
+
def select_assets(
|
|
686
|
+
df: pd.DataFrame,
|
|
687
|
+
n: int = 100,
|
|
688
|
+
start: Optional[str] = None,
|
|
689
|
+
end: Optional[str] = None,
|
|
690
|
+
rolling_window: Optional[int] = None,
|
|
691
|
+
) -> pd.DataFrame:
|
|
681
692
|
"""
|
|
682
693
|
Selects the top N assets based on the average trading volume from the input DataFrame.
|
|
683
694
|
These assets are used as universe in which we can search cointegrated pairs for pairs trading strategies.
|
|
@@ -744,7 +755,7 @@ def select_assets(df: pd.DataFrame, n=100, start=None, end=None, rolling_window=
|
|
|
744
755
|
return df.sort_index()
|
|
745
756
|
|
|
746
757
|
|
|
747
|
-
def compute_pair_metrics(security: pd.Series, candidates: pd.DataFrame):
|
|
758
|
+
def compute_pair_metrics(security: pd.Series, candidates: pd.DataFrame) -> pd.DataFrame:
|
|
748
759
|
"""Calculate statistical and econometric metrics for a security pair.
|
|
749
760
|
|
|
750
761
|
These metrics are useful in financial modeling and pairs trading strategies,
|
|
@@ -830,11 +841,11 @@ __CRITICAL_VALUES = {
|
|
|
830
841
|
def find_cointegrated_pairs(
|
|
831
842
|
securities: pd.DataFrame,
|
|
832
843
|
candidates: pd.DataFrame,
|
|
833
|
-
n=None,
|
|
834
|
-
start=None,
|
|
835
|
-
stop=None,
|
|
836
|
-
coint=False,
|
|
837
|
-
):
|
|
844
|
+
n: Optional[int] = None,
|
|
845
|
+
start: Optional[str] = None,
|
|
846
|
+
stop: Optional[str] = None,
|
|
847
|
+
coint: bool = False,
|
|
848
|
+
) -> pd.DataFrame:
|
|
838
849
|
"""
|
|
839
850
|
Identifies cointegrated pairs between a target set of securities and candidate securities
|
|
840
851
|
based on econometric tests. The function evaluates statistical relationships,
|
|
@@ -900,16 +911,17 @@ def find_cointegrated_pairs(
|
|
|
900
911
|
>>> top_pairs = find_cointegrated_pairs(securities, candidates, n=2, coint=True)
|
|
901
912
|
>>> print(top_pairs)
|
|
902
913
|
"""
|
|
914
|
+
...
|
|
903
915
|
|
|
904
916
|
|
|
905
917
|
def analyze_cointegrated_pairs(
|
|
906
918
|
spreads: pd.DataFrame,
|
|
907
|
-
plot_coint=True,
|
|
908
|
-
crosstab=False,
|
|
909
|
-
heuristics=False,
|
|
910
|
-
log_reg=False,
|
|
911
|
-
decis_tree=False,
|
|
912
|
-
):
|
|
919
|
+
plot_coint: bool = True,
|
|
920
|
+
crosstab: bool = False,
|
|
921
|
+
heuristics: bool = False,
|
|
922
|
+
log_reg: bool = False,
|
|
923
|
+
decis_tree: bool = False,
|
|
924
|
+
) -> None:
|
|
913
925
|
"""
|
|
914
926
|
Analyzes cointegrated pairs by visualizing, summarizing, and applying predictive models.
|
|
915
927
|
|
|
@@ -919,7 +931,7 @@ def analyze_cointegrated_pairs(
|
|
|
919
931
|
Required columns: 'coint', 't', 'trace0', 'trace1', 'drift', 'vol', 'corr', 'corr_ret', 'eg_sig', 'joh_sig'.
|
|
920
932
|
plot_coint (bool, optional):
|
|
921
933
|
If True, generates scatterplots and boxplots to visualize cointegration characteristics.
|
|
922
|
-
|
|
934
|
+
crosstab (bool, optional):
|
|
923
935
|
If True, displays crosstabulations of Engle-Granger and Johansen test significance.
|
|
924
936
|
heuristics (bool, optional):
|
|
925
937
|
If True, prints descriptive statistics for drift, volatility, and correlation grouped by cointegration status.
|
|
@@ -948,7 +960,7 @@ def analyze_cointegrated_pairs(
|
|
|
948
960
|
... })
|
|
949
961
|
|
|
950
962
|
>>> pairs = find_cointegrated_pairs(securities, candidates, n=2, coint=True)
|
|
951
|
-
>>> analyze_cointegrated_pairs(pairs, plot_coint=True,
|
|
963
|
+
>>> analyze_cointegrated_pairs(pairs, plot_coint=True, crosstab=True, heuristics=True, log_reg=True, decis_tree=True)
|
|
952
964
|
"""
|
|
953
965
|
if plot_coint:
|
|
954
966
|
trace0_cv = __CRITICAL_VALUES[0][0.95]
|
|
@@ -1006,7 +1018,9 @@ def analyze_cointegrated_pairs(
|
|
|
1006
1018
|
print(pd.crosstab(spreads.eg_sig, spreads.joh_sig, normalize=True))
|
|
1007
1019
|
|
|
1008
1020
|
|
|
1009
|
-
def select_candidate_pairs(
|
|
1021
|
+
def select_candidate_pairs(
|
|
1022
|
+
pairs: pd.DataFrame, period: bool = False
|
|
1023
|
+
) -> List[Dict[str, Any]]:
|
|
1010
1024
|
"""
|
|
1011
1025
|
Select candidate pairs from a DataFrame based on cointegration status.
|
|
1012
1026
|
|
|
@@ -1039,7 +1053,7 @@ def select_candidate_pairs(pairs: pd.DataFrame, period=False):
|
|
|
1039
1053
|
return candidates[["x", "y"]].to_dict(orient="records")
|
|
1040
1054
|
|
|
1041
1055
|
|
|
1042
|
-
def KFSmoother(prices: pd.Series
|
|
1056
|
+
def KFSmoother(prices: Union[pd.Series, np.ndarray]) -> Union[pd.Series, np.ndarray]:
|
|
1043
1057
|
"""
|
|
1044
1058
|
Estimate rolling mean using Kalman Smoothing.
|
|
1045
1059
|
|
|
@@ -1090,7 +1104,9 @@ def KFSmoother(prices: pd.Series | np.ndarray) -> pd.Series | np.ndarray:
|
|
|
1090
1104
|
return state_means.flatten()
|
|
1091
1105
|
|
|
1092
1106
|
|
|
1093
|
-
def KFHedgeRatio(
|
|
1107
|
+
def KFHedgeRatio(
|
|
1108
|
+
x: Union[pd.Series, np.ndarray], y: Union[pd.Series, np.ndarray]
|
|
1109
|
+
) -> np.ndarray:
|
|
1094
1110
|
"""Estimate Hedge Ratio using Kalman Filter.
|
|
1095
1111
|
|
|
1096
1112
|
This function uses a Kalman Filter to dynamically estimate the hedge ratio
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bbstrader
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Summary: Simplified Investment & Trading Toolkit
|
|
5
|
-
Author-email: Bertin Balouki SIMYELI <bertin@
|
|
6
|
-
Maintainer-email: Bertin Balouki SIMYELI <bertin@
|
|
5
|
+
Author-email: Bertin Balouki SIMYELI <bertin@bbs-trading.com>
|
|
6
|
+
Maintainer-email: Bertin Balouki SIMYELI <bertin@bbs-trading.com>
|
|
7
7
|
License-Expression: MIT
|
|
8
8
|
Project-URL: Homepage, https://github.com/bbalouki/bbstrader
|
|
9
9
|
Project-URL: Download, https://pypi.org/project/bbstrader/
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
bbstrader/__init__.py,sha256=
|
|
2
|
-
bbstrader/__main__.py,sha256=
|
|
3
|
-
bbstrader/compat.py,sha256=
|
|
4
|
-
bbstrader/config.py,sha256=
|
|
5
|
-
bbstrader/tseries.py,sha256=
|
|
1
|
+
bbstrader/__init__.py,sha256=bsyhtdTioj1KZyaAnEN6oE0Wvq8z0HaFEzPe8yWyxFo,749
|
|
2
|
+
bbstrader/__main__.py,sha256=KtGegYzmlp78YGuDIW75ouxLyWaRPNC4nC-Qcg8wheE,2751
|
|
3
|
+
bbstrader/compat.py,sha256=5gj2Yycv3W50BfaPDqC3sKZOwTP2AbD_MFfiL8DJYqg,682
|
|
4
|
+
bbstrader/config.py,sha256=4n6jS0x1E2kEVvCxFaRI6HRaGnJqPz1hhUofquwvsMk,2959
|
|
5
|
+
bbstrader/tseries.py,sha256=O6RG2ame_i6jGT7nETizb3uy7pwxrToRRJDKCUNupoQ,42800
|
|
6
6
|
bbstrader/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
bbstrader/apps/_copier.py,sha256=
|
|
7
|
+
bbstrader/apps/_copier.py,sha256=61PBMo5f429pDJ-XchTivZ1Y0whFLl2ZtdyFHJfmsxQ,25970
|
|
8
8
|
bbstrader/btengine/__init__.py,sha256=y1btjaEfhWsH8vuE7mBRpP9Tu-Azt9REhuVYsPCAfBU,2955
|
|
9
|
-
bbstrader/btengine/backtest.py,sha256=
|
|
10
|
-
bbstrader/btengine/data.py,sha256=
|
|
11
|
-
bbstrader/btengine/event.py,sha256=
|
|
12
|
-
bbstrader/btengine/execution.py,sha256=
|
|
13
|
-
bbstrader/btengine/performance.py,sha256=
|
|
14
|
-
bbstrader/btengine/portfolio.py,sha256=
|
|
15
|
-
bbstrader/btengine/scripts.py,sha256=
|
|
16
|
-
bbstrader/btengine/strategy.py,sha256=
|
|
9
|
+
bbstrader/btengine/backtest.py,sha256=4O0ZnkhJ1nu3zWaGCrXQVKhfqW46jsqdMIPmsUPLyYo,14979
|
|
10
|
+
bbstrader/btengine/data.py,sha256=03ahVmqXQefx8gaH16fLBP1rIikfKqmJ4PULm1Q29TU,28760
|
|
11
|
+
bbstrader/btengine/event.py,sha256=E_OvwAO23xl0FqH-oe5Dh83fDmSjuF_KS8kOi8SEhTc,8880
|
|
12
|
+
bbstrader/btengine/execution.py,sha256=RFH2xIhiUGv9nqyvupBNuCmw3rjRgO7h2ySP_3Ggei0,12182
|
|
13
|
+
bbstrader/btengine/performance.py,sha256=WT4jz5AnOr8Eenz6NNR6po8Q8brMDIJskCS0o3mWy40,12764
|
|
14
|
+
bbstrader/btengine/portfolio.py,sha256=bqcVuohDZqertLo6LEk7DIY6e3Npi0UKQUKawEmo5Ko,16695
|
|
15
|
+
bbstrader/btengine/scripts.py,sha256=5wRzyxGxA6C8cd_tRDrr-p_7_TtWWk0zIxzblZxP3M4,5178
|
|
16
|
+
bbstrader/btengine/strategy.py,sha256=D72lULYu1tth9KUm4RS7EtrJdDqa1EF4uH8wlqrTTYQ,44666
|
|
17
17
|
bbstrader/core/__init__.py,sha256=GIFzFSStPfE0XM2j7mDeZZQeMTh_AwPsDOQXwMVJLgw,97
|
|
18
|
-
bbstrader/core/data.py,sha256=
|
|
19
|
-
bbstrader/core/scripts.py,sha256=
|
|
20
|
-
bbstrader/core/utils.py,sha256=
|
|
18
|
+
bbstrader/core/data.py,sha256=KJCGSfTGJNfLWOAytfRM4-BVNV1M6QfvH4DWB-4v4cA,26146
|
|
19
|
+
bbstrader/core/scripts.py,sha256=cdw0X12-8IHsr8pg6x_fMsUg_UhFFWDy9lXY52Vpou8,5777
|
|
20
|
+
bbstrader/core/utils.py,sha256=8PsJm73LMJf1lCjfxDlqU32U4GhWPVcUTOyyETM7fLs,3124
|
|
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
|
|
@@ -37,11 +37,11 @@ bbstrader/models/optimization.py,sha256=Fa4tdhynMmvKt5KHV9cH1TXmmJVJwU4QWpYkbeVq
|
|
|
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=
|
|
40
|
+
bbstrader/trading/execution.py,sha256=P1SrV5CKhSbi2NhztPO3pEtGVHOXkfHEdWAVYzeaMWw,42086
|
|
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.
|
|
44
|
+
bbstrader-0.3.7.dist-info/licenses/LICENSE,sha256=ZwC_RqqGmOPBUiMDKqLyJZ5HBeHq53LpL7TMRzrJY8c,1094
|
|
45
45
|
docs/conf.py,sha256=q_Z8_iz-YDgHhe4PpCOAtvN5Q-2hHquliG07FDEXdjo,1686
|
|
46
46
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
47
47
|
tests/engine/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
@@ -49,14 +49,14 @@ tests/engine/test_backtest.py,sha256=OmHimBp518BBv0Eg-t_cIrBXMzfiYOGki5FW7kqFeFs
|
|
|
49
49
|
tests/engine/test_data.py,sha256=jAVICMt4YTKF5PN6ZIxhQ9CuUjbw9_gIPAC4sNA9GsE,19907
|
|
50
50
|
tests/engine/test_events.py,sha256=is3v3mtQVKFVNyn-xF4F7yuBGA5vqgunqsoFgNJeH0c,11755
|
|
51
51
|
tests/engine/test_execution.py,sha256=Sk3d_Rl9T0GjArficd75hEeVyeB_7yOcTD8ltpN4UlY,7961
|
|
52
|
-
tests/engine/test_portfolio.py,sha256=
|
|
52
|
+
tests/engine/test_portfolio.py,sha256=Anx6TtgCdyyhqfoui2kwuX8X5gtisT2tL5yZNJOUbKw,9865
|
|
53
53
|
tests/metatrader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
54
|
tests/metatrader/test_account.py,sha256=UiAWP0IRd6a1kmA_pTcEuCZAJjtq0U_Q-PcOdd2l69A,68627
|
|
55
55
|
tests/metatrader/test_rates.py,sha256=dc43jAvkZby9TMJcwkcaEvH21jQudk1D8KQxWLlAYoQ,10424
|
|
56
56
|
tests/metatrader/test_risk_management.py,sha256=lMT0m7dmT3iWihTkEwpMoHdJPPWU3XJmqgCV4qKT-uw,31019
|
|
57
57
|
tests/metatrader/test_trade.py,sha256=gMyinOOgVC2SOV8xLMIKqUTwqXbSUuDGnhSmspXK9cw,15177
|
|
58
|
-
bbstrader-0.3.
|
|
59
|
-
bbstrader-0.3.
|
|
60
|
-
bbstrader-0.3.
|
|
61
|
-
bbstrader-0.3.
|
|
62
|
-
bbstrader-0.3.
|
|
58
|
+
bbstrader-0.3.7.dist-info/METADATA,sha256=2l53CAyYDuXnRg0duIlsMFiGjDtGVOVYMrJwgfSWVzQ,26697
|
|
59
|
+
bbstrader-0.3.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
60
|
+
bbstrader-0.3.7.dist-info/entry_points.txt,sha256=0yDCbhbgHswOzJnY5wRSM_FjjyMHGvY7lJpSSVh0xtI,54
|
|
61
|
+
bbstrader-0.3.7.dist-info/top_level.txt,sha256=raTnmqZJ2B3Mvrhy_fV9szurE9yVctrKHBLZ1NJ5vnU,21
|
|
62
|
+
bbstrader-0.3.7.dist-info/RECORD,,
|
tests/engine/test_portfolio.py
CHANGED
|
@@ -18,7 +18,7 @@ class MockDataHandler:
|
|
|
18
18
|
"""A mock DataHandler to control market data during tests."""
|
|
19
19
|
|
|
20
20
|
def __init__(self, symbol_list, initial_data):
|
|
21
|
-
self.
|
|
21
|
+
self.symbols = symbol_list
|
|
22
22
|
self.latest_symbol_data = initial_data
|
|
23
23
|
|
|
24
24
|
def get_latest_bar_datetime(self, symbol):
|
|
@@ -90,7 +90,7 @@ def test_initialization(basic_portfolio):
|
|
|
90
90
|
def test_tf_mapping_and_initialization_error():
|
|
91
91
|
"""Tests the timeframe mapping and ensures invalid timeframes raise errors."""
|
|
92
92
|
mock_bars = MagicMock()
|
|
93
|
-
mock_bars.
|
|
93
|
+
mock_bars.symbols = ["DUMMY"]
|
|
94
94
|
|
|
95
95
|
# Test a valid timeframe
|
|
96
96
|
p = Portfolio(
|
|
@@ -210,6 +210,7 @@ def test_update_signal_puts_order_on_queue(basic_portfolio):
|
|
|
210
210
|
assert order.direction == "BUY"
|
|
211
211
|
assert order.quantity == 50 # 100 * 0.5
|
|
212
212
|
|
|
213
|
+
|
|
213
214
|
@pytest.mark.filterwarnings("ignore")
|
|
214
215
|
@patch("bbstrader.btengine.performance.plt.show")
|
|
215
216
|
@patch("bbstrader.btengine.portfolio.plot_performance")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|