bbstrader 0.3.4__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.

Files changed (38) hide show
  1. bbstrader/__init__.py +10 -1
  2. bbstrader/__main__.py +5 -0
  3. bbstrader/apps/_copier.py +3 -3
  4. bbstrader/btengine/strategy.py +113 -38
  5. bbstrader/compat.py +18 -10
  6. bbstrader/config.py +0 -16
  7. bbstrader/core/scripts.py +4 -3
  8. bbstrader/metatrader/account.py +51 -26
  9. bbstrader/metatrader/analysis.py +30 -16
  10. bbstrader/metatrader/copier.py +136 -58
  11. bbstrader/metatrader/trade.py +39 -45
  12. bbstrader/metatrader/utils.py +5 -4
  13. bbstrader/models/factors.py +17 -13
  14. bbstrader/models/ml.py +96 -49
  15. bbstrader/models/nlp.py +83 -66
  16. bbstrader/trading/execution.py +39 -22
  17. bbstrader/tseries.py +103 -127
  18. {bbstrader-0.3.4.dist-info → bbstrader-0.3.6.dist-info}/METADATA +29 -46
  19. bbstrader-0.3.6.dist-info/RECORD +62 -0
  20. bbstrader-0.3.6.dist-info/top_level.txt +3 -0
  21. docs/conf.py +56 -0
  22. tests/__init__.py +0 -0
  23. tests/engine/__init__.py +1 -0
  24. tests/engine/test_backtest.py +58 -0
  25. tests/engine/test_data.py +536 -0
  26. tests/engine/test_events.py +300 -0
  27. tests/engine/test_execution.py +219 -0
  28. tests/engine/test_portfolio.py +307 -0
  29. tests/metatrader/__init__.py +0 -0
  30. tests/metatrader/test_account.py +1769 -0
  31. tests/metatrader/test_rates.py +292 -0
  32. tests/metatrader/test_risk_management.py +700 -0
  33. tests/metatrader/test_trade.py +439 -0
  34. bbstrader-0.3.4.dist-info/RECORD +0 -49
  35. bbstrader-0.3.4.dist-info/top_level.txt +0 -1
  36. {bbstrader-0.3.4.dist-info → bbstrader-0.3.6.dist-info}/WHEEL +0 -0
  37. {bbstrader-0.3.4.dist-info → bbstrader-0.3.6.dist-info}/entry_points.txt +0 -0
  38. {bbstrader-0.3.4.dist-info → bbstrader-0.3.6.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,439 @@
1
+ import unittest
2
+ from datetime import datetime
3
+ from unittest.mock import MagicMock, patch
4
+
5
+ from bbstrader.metatrader.trade import (
6
+ Trade,
7
+ TradeAction,
8
+ TradeSignal,
9
+ TradingMode,
10
+ create_trade_instance,
11
+ generate_signal,
12
+ )
13
+ from bbstrader.metatrader.utils import (
14
+ AccountInfo,
15
+ SymbolInfo,
16
+ TickInfo,
17
+ TradeOrder,
18
+ TradePosition,
19
+ )
20
+
21
+
22
+ class TestTrade(unittest.TestCase):
23
+ def setUp(self):
24
+ """Set up the test environment."""
25
+ self.mt5_patcher = patch("bbstrader.metatrader.trade.Mt5")
26
+ self.mock_mt5 = self.mt5_patcher.start()
27
+ self.addCleanup(self.mt5_patcher.stop)
28
+
29
+ self.logger_patcher = patch("bbstrader.metatrader.trade.log")
30
+ self.mock_logger = self.logger_patcher.start()
31
+ self.addCleanup(self.logger_patcher.stop)
32
+
33
+ patch(
34
+ "bbstrader.metatrader.risk.RiskManagement.__init__", return_value=None
35
+ ).start()
36
+ self.addCleanup(patch.stopall)
37
+
38
+ patch("bbstrader.metatrader.trade.check_mt5_connection").start()
39
+ patch("bbstrader.metatrader.trade.Trade.select_symbol").start()
40
+ patch("bbstrader.metatrader.trade.Trade.prepare_symbol").start()
41
+
42
+ self.account_info = AccountInfo(
43
+ login=12345,
44
+ balance=10000.0,
45
+ equity=10000.0,
46
+ currency="USD",
47
+ name="Test Account",
48
+ server="Test Server",
49
+ leverage=100,
50
+ trade_mode=0,
51
+ limit_orders=0,
52
+ margin_so_mode=0,
53
+ trade_allowed=True,
54
+ trade_expert=True,
55
+ margin_mode=0,
56
+ currency_digits=2,
57
+ fifo_close=False,
58
+ credit=0.0,
59
+ profit=0.0,
60
+ margin=0.0,
61
+ margin_free=10000.0,
62
+ margin_level=0.0,
63
+ margin_so_call=0.0,
64
+ margin_so_so=0.0,
65
+ margin_initial=0.0,
66
+ margin_maintenance=0.0,
67
+ assets=0.0,
68
+ liabilities=0.0,
69
+ commission_blocked=0.0,
70
+ company="MetaQuotes",
71
+ )
72
+ self.symbol_info = SymbolInfo(
73
+ name="EURUSD",
74
+ visible=True,
75
+ point=0.00001,
76
+ digits=5,
77
+ spread=10,
78
+ trade_tick_value=1.0,
79
+ trade_tick_size=0.00001,
80
+ trade_contract_size=100000,
81
+ volume_min=0.01,
82
+ volume_max=100.0,
83
+ volume_step=0.01,
84
+ bid=1.10000,
85
+ ask=1.10010,
86
+ time=datetime.now(),
87
+ custom=False,
88
+ chart_mode=0,
89
+ select=True,
90
+ session_deals=0,
91
+ session_buy_orders=0,
92
+ session_sell_orders=0,
93
+ volume=0,
94
+ volumehigh=0,
95
+ volumelow=0,
96
+ bidhigh=0,
97
+ bidlow=0,
98
+ askhigh=0,
99
+ asklow=0,
100
+ last=0,
101
+ lasthigh=0,
102
+ lastlow=0,
103
+ volume_real=0,
104
+ volumehigh_real=0,
105
+ volumelow_real=0,
106
+ option_strike=0,
107
+ trade_tick_value_profit=1.0,
108
+ trade_tick_value_loss=1.0,
109
+ trade_stops_level=0,
110
+ trade_freeze_level=0,
111
+ trade_exemode=0,
112
+ swap_mode=0,
113
+ swap_rollover3days=0,
114
+ margin_hedged_use_leg=False,
115
+ expiration_mode=0,
116
+ filling_mode=0,
117
+ order_mode=0,
118
+ order_gtc_mode=0,
119
+ option_mode=0,
120
+ option_right=0,
121
+ margin_initial=0,
122
+ margin_maintenance=0,
123
+ session_volume=0,
124
+ session_turnover=0,
125
+ session_interest=0,
126
+ session_buy_orders_volume=0,
127
+ session_sell_orders_volume=0,
128
+ session_open=0,
129
+ session_close=0,
130
+ session_aw=0,
131
+ session_price_settlement=0,
132
+ session_price_limit_min=0,
133
+ session_price_limit_max=0,
134
+ margin_hedged=0,
135
+ price_change=0,
136
+ price_volatility=0,
137
+ price_theoretical=0,
138
+ price_greeks_delta=0,
139
+ price_greeks_theta=0,
140
+ price_greeks_gamma=0,
141
+ price_greeks_vega=0,
142
+ price_greeks_rho=0,
143
+ price_greeks_omega=0,
144
+ price_sensitivity=0,
145
+ basis="",
146
+ category="",
147
+ currency_base="EUR",
148
+ currency_profit="USD",
149
+ currency_margin="EUR",
150
+ bank="",
151
+ description="Euro vs US Dollar",
152
+ exchange="",
153
+ formula="",
154
+ isin="",
155
+ page="",
156
+ path="Forex\\Majors\\EURUSD",
157
+ start_time=0,
158
+ expiration_time=0,
159
+ spread_float=True,
160
+ ticks_bookdepth=0,
161
+ trade_calc_mode=0,
162
+ trade_mode=0,
163
+ trade_accrued_interest=0.0,
164
+ trade_face_value=0.0,
165
+ trade_liquidity_rate=0.0,
166
+ volume_limit=0.0,
167
+ swap_long=0.0,
168
+ swap_short=0.0,
169
+ )
170
+ self.tick_info = TickInfo(
171
+ time=datetime.now(),
172
+ bid=1.10000,
173
+ ask=1.10010,
174
+ last=1.10005,
175
+ volume=100,
176
+ time_msc=int(datetime.now().timestamp() * 1000),
177
+ flags=6,
178
+ volume_real=100.0,
179
+ )
180
+
181
+ self.trade = Trade(symbol="EURUSD", expert_id=98181105, verbose=False)
182
+
183
+ # Manually set attributes from the patched RiskManagement parent class
184
+ self.trade.symbol_info = self.symbol_info
185
+ self.trade.account_leverage = True
186
+ self.trade.be = 10
187
+ self.trade.max_risk = 5.0
188
+ self.trade.rr = 2.0
189
+ self.trade.copy_mode = False
190
+
191
+ # Patch instance methods to return mock data
192
+ patch.object(
193
+ self.trade, "get_account_info", return_value=self.account_info
194
+ ).start()
195
+ patch.object(
196
+ self.trade, "get_symbol_info", return_value=self.symbol_info
197
+ ).start()
198
+ patch.object(self.trade, "get_tick_info", return_value=self.tick_info).start()
199
+ patch.object(self.trade, "get_lot", return_value=0.1).start()
200
+ patch.object(self.trade, "get_stop_loss", return_value=200).start()
201
+ patch.object(self.trade, "get_take_profit", return_value=300).start()
202
+ patch.object(
203
+ self.trade,
204
+ "send_order",
205
+ return_value=MagicMock(retcode=self.mock_mt5.TRADE_RETCODE_DONE, order=123),
206
+ ).start()
207
+ # This patch is crucial to prevent the UnboundLocalError in close_request
208
+ patch.object(self.trade, "check_order", return_value=True).start()
209
+
210
+ def tearDown(self):
211
+ """This method is no longer needed as addCleanup handles stopping patches."""
212
+ pass
213
+
214
+ def test_trade_signal_initialization(self):
215
+ """Test TradeSignal dataclass initialization and validation."""
216
+ signal = TradeSignal(id=1, symbol="EURUSD", action=TradeAction.BUY, price=1.2)
217
+ self.assertEqual(signal.id, 1)
218
+ self.assertEqual(signal.action, TradeAction.BUY)
219
+
220
+ with self.assertRaises(TypeError):
221
+ TradeSignal(id=1, symbol="EURUSD", action="BUY", price=1.2)
222
+
223
+ with self.assertRaises(ValueError):
224
+ TradeSignal(id=1, symbol="EURUSD", action=TradeAction.BUY, stoplimit=1.2)
225
+
226
+ def test_generate_signal(self):
227
+ """Test the generate_signal factory function."""
228
+ signal = generate_signal(
229
+ id=1, symbol="EURUSD", action=TradeAction.SELL, price=1.3
230
+ )
231
+ self.assertIsInstance(signal, TradeSignal)
232
+ self.assertEqual(signal.price, 1.3)
233
+
234
+ def test_trading_mode_enum(self):
235
+ """Test the TradingMode enum."""
236
+ self.assertTrue(TradingMode.BACKTEST.isbacktest())
237
+ self.assertFalse(TradingMode.LIVE.isbacktest())
238
+ self.assertTrue(TradingMode.LIVE.islive())
239
+ self.assertFalse(TradingMode.BACKTEST.islive())
240
+
241
+ @patch("bbstrader.metatrader.trade.tabulate")
242
+ @patch("builtins.print")
243
+ def test_summary(self, mock_print, mock_tabulate):
244
+ """Test the summary method."""
245
+ self.trade.summary()
246
+ mock_tabulate.assert_called_once()
247
+ mock_print.assert_called()
248
+
249
+ @patch("bbstrader.metatrader.trade.tabulate")
250
+ @patch("builtins.print")
251
+ def test_risk_management_summary(self, mock_print, mock_tabulate):
252
+ """Test the risk_managment method."""
253
+ with (
254
+ patch.object(
255
+ self.trade, "get_stats", return_value=({}, {"total_profit": 100})
256
+ ),
257
+ patch.object(
258
+ self.trade,
259
+ "currency_risk",
260
+ return_value={"trade_loss": 10, "trade_profit": 20},
261
+ ),
262
+ patch.object(self.trade, "get_currency_rates", return_value={"mc": "EUR"}),
263
+ patch.object(self.trade, "is_risk_ok", return_value=True),
264
+ patch.object(self.trade, "risk_level", return_value=1.0),
265
+ patch.object(self.trade, "get_leverage", return_value="1:100"),
266
+ patch.object(self.trade, "volume", return_value=0.1),
267
+ patch.object(self.trade, "get_currency_risk", return_value=100),
268
+ patch.object(self.trade, "expected_profit", return_value=200),
269
+ patch.object(self.trade, "get_break_even", return_value=50),
270
+ patch.object(self.trade, "get_deviation", return_value=20),
271
+ patch.object(self.trade, "get_minutes", return_value=60),
272
+ patch.object(self.trade, "max_trade", return_value=10),
273
+ ):
274
+ self.trade.risk_managment()
275
+ mock_tabulate.assert_called_once()
276
+ mock_print.assert_called()
277
+
278
+ @patch("pandas.DataFrame.to_csv")
279
+ @patch("os.makedirs")
280
+ def test_statistics(self, mock_makedirs, mock_to_csv):
281
+ """Test the statistics method."""
282
+ stats1 = {
283
+ "deals": 1,
284
+ "profit": 100,
285
+ "win_trades": 1,
286
+ "loss_trades": 0,
287
+ "total_fees": -10,
288
+ "average_fee": -10,
289
+ "win_rate": 100,
290
+ }
291
+ stats2 = {"total_profit": 90, "profitability": "Yes"}
292
+ with (
293
+ patch.object(self.trade, "get_stats", return_value=(stats1, stats2)),
294
+ patch.object(self.trade, "sharpe", return_value=1.5),
295
+ patch.object(self.trade, "get_currency_risk", return_value=100),
296
+ patch.object(self.trade, "expected_profit", return_value=200),
297
+ ):
298
+ self.trade.statistics(save=True, dir="test_stats")
299
+ mock_makedirs.assert_called_with("test_stats", exist_ok=True)
300
+ mock_to_csv.assert_called_once()
301
+
302
+ def test_open_buy_position(self):
303
+ """Test opening a buy position."""
304
+ with patch.object(self.trade, "check", return_value=True):
305
+ result = self.trade.open_buy_position(action="BMKT")
306
+ self.assertTrue(result)
307
+ self.trade.send_order.assert_called()
308
+
309
+ def test_open_sell_position(self):
310
+ """Test opening a sell position."""
311
+ with patch.object(self.trade, "check", return_value=True):
312
+ result = self.trade.open_sell_position(action="SMKT")
313
+ self.assertTrue(result)
314
+ self.trade.send_order.assert_called()
315
+
316
+ def test_open_position(self):
317
+ """Test the generic open_position method."""
318
+ with patch.object(self.trade, "open_buy_position") as mock_buy:
319
+ self.trade.open_position(action="BMKT")
320
+ mock_buy.assert_called_once()
321
+
322
+ with patch.object(self.trade, "open_sell_position") as mock_sell:
323
+ self.trade.open_position(action="SMKT")
324
+ mock_sell.assert_called_once()
325
+
326
+ with self.assertRaises(ValueError):
327
+ self.trade.open_position(action="INVALID_ACTION")
328
+
329
+ def test_close_position(self):
330
+ """Test closing a position."""
331
+ position = self._get_mock_position(ticket=123)
332
+ with patch.object(self.trade, "get_positions", return_value=[position]):
333
+ result = self.trade.close_position(ticket=123)
334
+ self.assertTrue(result)
335
+ self.trade.send_order.assert_called()
336
+
337
+ def test_close_order(self):
338
+ """Test closing an order."""
339
+ with patch.object(
340
+ self.trade, "close_request", return_value=True
341
+ ) as mock_close_request:
342
+ result = self.trade.close_order(ticket=456)
343
+ self.assertTrue(result)
344
+ mock_close_request.assert_called_once()
345
+
346
+ def test_modify_order(self):
347
+ """Test modifying an order."""
348
+ order = self._get_mock_order(ticket=789)
349
+ with (
350
+ patch.object(self.trade, "get_orders", return_value=[order]),
351
+ patch.object(self.trade, "check_order", return_value=True),
352
+ ):
353
+ self.trade.modify_order(ticket=789, price=1.15)
354
+ self.trade.send_order.assert_called()
355
+ call_args = self.trade.send_order.call_args[0][0]
356
+ self.assertEqual(call_args["price"], 1.15)
357
+
358
+ def test_create_trade_instance(self):
359
+ """Test the create_trade_instance factory function."""
360
+ with patch("bbstrader.metatrader.trade.Trade") as mock_trade:
361
+ params = {"expert_id": 123}
362
+ symbols = ["EURUSD", "GBPUSD"]
363
+ instances = create_trade_instance(symbols, params)
364
+ self.assertEqual(len(instances), 2)
365
+ self.assertIn("EURUSD", instances)
366
+ self.assertIn("GBPUSD", instances)
367
+ self.assertEqual(mock_trade.call_count, 2)
368
+
369
+ def _get_mock_position(
370
+ self,
371
+ ticket=1,
372
+ symbol="EURUSD",
373
+ volume=0.1,
374
+ price_open=1.1,
375
+ type=0,
376
+ magic=98181105,
377
+ profit=0.0,
378
+ ):
379
+ return TradePosition(
380
+ ticket=ticket,
381
+ time=int(datetime.now().timestamp()),
382
+ time_msc=0,
383
+ time_update=0,
384
+ time_update_msc=0,
385
+ type=type,
386
+ magic=magic,
387
+ identifier=0,
388
+ reason=0,
389
+ volume=volume,
390
+ price_open=price_open,
391
+ sl=0,
392
+ tp=0,
393
+ price_current=price_open + 0.001,
394
+ swap=0,
395
+ profit=profit,
396
+ symbol=symbol,
397
+ comment="test",
398
+ external_id="",
399
+ )
400
+
401
+ def _get_mock_order(
402
+ self,
403
+ ticket=1,
404
+ symbol="EURUSD",
405
+ price_open=1.1,
406
+ volume_initial=0.1,
407
+ type=0,
408
+ magic=98181105,
409
+ ):
410
+ return TradeOrder(
411
+ ticket=ticket,
412
+ time_setup=int(datetime.now().timestamp()),
413
+ time_setup_msc=0,
414
+ time_done=0,
415
+ time_done_msc=0,
416
+ time_expiration=0,
417
+ type=type,
418
+ type_time=0,
419
+ type_filling=0,
420
+ state=0,
421
+ magic=magic,
422
+ position_id=0,
423
+ position_by_id=0,
424
+ reason=0,
425
+ volume_initial=volume_initial,
426
+ volume_current=0.1,
427
+ price_open=price_open,
428
+ sl=0,
429
+ tp=0,
430
+ price_current=price_open,
431
+ price_stoplimit=0,
432
+ symbol=symbol,
433
+ comment="test",
434
+ external_id="",
435
+ )
436
+
437
+
438
+ if __name__ == "__main__":
439
+ unittest.main()
@@ -1,49 +0,0 @@
1
- bbstrader/__init__.py,sha256=4KVGBEYU3ao9zPVM3rMWqNuvCleCeA6C2MVe_AFc4rw,581
2
- bbstrader/__main__.py,sha256=RjUIJWaD2_Od8ZMSLL8dzc2ZuCkkzlvNaE7-LIu3RGU,2488
3
- bbstrader/compat.py,sha256=djbHMvTvy0HYm1zyZ6Ttp_LMwP2PqTSVw1r7pqbz7So,487
4
- bbstrader/config.py,sha256=riZxwb4hN0I-dSsWcjnROc5dWQpSJ9iKOMIp4PMGfko,3970
5
- bbstrader/tseries.py,sha256=SM_LTQHJ3ZXVkVJyZ51CefUDzJDl2TkJqBKMp_uM8s4,43833
6
- bbstrader/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- bbstrader/apps/_copier.py,sha256=z6GhLSmFjHc_oh7pYRTflH42Xmpe3Z7B2fUyedzDQPo,25387
8
- bbstrader/btengine/__init__.py,sha256=y1btjaEfhWsH8vuE7mBRpP9Tu-Azt9REhuVYsPCAfBU,2955
9
- bbstrader/btengine/backtest.py,sha256=o3eoCVzpjykDx-9VgkxK6DKZdGDAuLVeeWLCa2U_zeY,14652
10
- bbstrader/btengine/data.py,sha256=WcBLtabboZkQdtOQS3SjbiJD9BcWc75sdhZ2voQ_lUw,27061
11
- bbstrader/btengine/event.py,sha256=Ydl1avAXp9WAWOBXDAckcb9g1UkcnCO0rRzcJZwIq20,8714
12
- bbstrader/btengine/execution.py,sha256=4MytWjcKg8J_w14P43emHqsvKOElkQTfhVYNakU6euQ,11190
13
- bbstrader/btengine/performance.py,sha256=1ecWrTzHBQbk4ORvbTEKxwCzlL1brcXOEUwgbnjAwx4,12470
14
- bbstrader/btengine/portfolio.py,sha256=z98M65HQeCyma8gMZkAxspxBA9jtIhzxMyJUHPPj34c,16128
15
- bbstrader/btengine/scripts.py,sha256=8o66dq4Ex4DsH4s8xvJqUOFjLzZJSnbBvvNBzohtzoE,4837
16
- bbstrader/btengine/strategy.py,sha256=hDghr5sXNitWlWXXvgl8Vj-QHWaIuVlx54LUXAbQrHQ,36725
17
- bbstrader/core/__init__.py,sha256=GIFzFSStPfE0XM2j7mDeZZQeMTh_AwPsDOQXwMVJLgw,97
18
- bbstrader/core/data.py,sha256=5-ByClb-E3-iqDz8CBJ4om9wBIA7DmUWezu4A-tv5ys,25095
19
- bbstrader/core/scripts.py,sha256=bMZ5I_hCTPCsAn9v9Sz9fQQ7JFkf_Zwtv7uUJwaqVBU,5466
20
- bbstrader/core/utils.py,sha256=tHXQimmmlYZHktNnYNKn_wVq6v-85pI7DXF6xlJV7ps,2780
21
- bbstrader/ibkr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- bbstrader/ibkr/utils.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
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=knGvLsiWUzM6eYe7CrKF6rTeReFdogdCQU5Q7p7UHmY,54186
27
- bbstrader/metatrader/rates.py,sha256=w9mr6FB6E1zLcHCDtDGt-oMnw6sakIU6Qe3455KDsSg,20782
28
- bbstrader/metatrader/risk.py,sha256=NhW8qtSg350Z6H9oLcDqOU_erqd_7Y7F5FwpfPN5Qso,27262
29
- bbstrader/metatrader/scripts.py,sha256=8meq6_zz6jPSibNgtYtaO8Ba-uJZOoLkpqYUIjidk-U,4010
30
- bbstrader/metatrader/trade.py,sha256=ezkALiUgtIu54R4m4blQjptWoRXNVG5wwuoctP2b90Y,80624
31
- bbstrader/metatrader/utils.py,sha256=PnFZ8EuBSZgsYlvwZDOxj4vUTtt-hUYnnwFBmu7gxxw,20738
32
- bbstrader/models/__init__.py,sha256=B-bn2h_SCK6gRAs2li6dDVnvV8jDT5suZimldk5xxcw,497
33
- bbstrader/models/factors.py,sha256=Y1rjwhWU4aiSRd-jFOLnLZczFCY0bJUxauCo17HvOFY,12791
34
- bbstrader/models/ml.py,sha256=d_maEXwGOGuWawisjIbMO5FUsaSjlgmJu5XiMu28Wf8,48921
35
- bbstrader/models/nlp.py,sha256=hcvz9d_8j1cIC1h3oqa1DBjExRIEd6WSiZb95Vr3NPo,32638
36
- bbstrader/models/optimization.py,sha256=Fa4tdhynMmvKt5KHV9cH1TXmmJVJwU4QWpYkbeVq4aI,6395
37
- bbstrader/models/portfolio.py,sha256=r-47Zrn2r7iKCHm5YVtwkbBJXAZGM3QYy-rXCWY9-Bg,8079
38
- bbstrader/models/risk.py,sha256=MKCk53HtGIcivrNzH8Ikm5KMs1rXhFT5zkorUf30PyQ,506
39
- bbstrader/trading/__init__.py,sha256=ycLyuuxN5SujqtzR9X0Q74UQfK93q2va-GGAXdr-KS8,457
40
- bbstrader/trading/execution.py,sha256=CYt4fageoqcpMFvdRH-jX4hexAGUiG_wE94i1qg7BFM,41479
41
- bbstrader/trading/scripts.py,sha256=Tf5q33WqqygjpIv43_8nA82VZ3GM0qgb4Ggo3fHJ_wg,5744
42
- bbstrader/trading/strategies.py,sha256=RZ6P4SfIyRW72v0OnPnrc4Hv8X00FdxR-_sD23xe_Pg,11756
43
- bbstrader/trading/utils.py,sha256=57dKF9dcRu04oU2VRqydRrzW39dCW2wlDWhVt-sZdRw,1857
44
- bbstrader-0.3.4.dist-info/licenses/LICENSE,sha256=ZwC_RqqGmOPBUiMDKqLyJZ5HBeHq53LpL7TMRzrJY8c,1094
45
- bbstrader-0.3.4.dist-info/METADATA,sha256=_Zc1Yp1Exs0wUpD0KV1G41uDnR3v7mhHWawRDbkutSM,27089
46
- bbstrader-0.3.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
- bbstrader-0.3.4.dist-info/entry_points.txt,sha256=0yDCbhbgHswOzJnY5wRSM_FjjyMHGvY7lJpSSVh0xtI,54
48
- bbstrader-0.3.4.dist-info/top_level.txt,sha256=Wwj322jZmxGZ6gD_TdaPiPLjED5ReObm5omerwlmZIg,10
49
- bbstrader-0.3.4.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- bbstrader