bbstrader 0.1.6__tar.gz → 0.1.8__tar.gz

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 (39) hide show
  1. {bbstrader-0.1.6 → bbstrader-0.1.8}/PKG-INFO +16 -7
  2. {bbstrader-0.1.6 → bbstrader-0.1.8}/README.md +12 -6
  3. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/__ini__.py +0 -1
  4. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/btengine/__init__.py +13 -9
  5. bbstrader-0.1.8/bbstrader/btengine/backtest.py +300 -0
  6. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/btengine/data.py +3 -1
  7. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/btengine/event.py +15 -9
  8. bbstrader-0.1.8/bbstrader/btengine/execution.py +143 -0
  9. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/btengine/performance.py +32 -20
  10. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/btengine/portfolio.py +33 -15
  11. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/btengine/strategy.py +1 -2
  12. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/metatrader/account.py +15 -8
  13. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/metatrader/rates.py +10 -6
  14. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/metatrader/risk.py +1 -2
  15. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/metatrader/trade.py +307 -239
  16. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/metatrader/utils.py +37 -29
  17. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/models/risk.py +39 -2
  18. bbstrader-0.1.8/bbstrader/trading/__init__.py +11 -0
  19. bbstrader-0.1.8/bbstrader/trading/execution.py +423 -0
  20. bbstrader-0.1.8/bbstrader/trading/strategies.py +840 -0
  21. bbstrader-0.1.8/bbstrader/tseries.py +1182 -0
  22. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader.egg-info/PKG-INFO +16 -7
  23. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader.egg-info/SOURCES.txt +1 -3
  24. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader.egg-info/requires.txt +3 -0
  25. {bbstrader-0.1.6 → bbstrader-0.1.8}/setup.py +4 -3
  26. bbstrader-0.1.6/bbstrader/btengine/backtest.py +0 -903
  27. bbstrader-0.1.6/bbstrader/btengine/execution.py +0 -83
  28. bbstrader-0.1.6/bbstrader/strategies.py +0 -681
  29. bbstrader-0.1.6/bbstrader/trading/__init__.py +0 -4
  30. bbstrader-0.1.6/bbstrader/trading/execution.py +0 -977
  31. bbstrader-0.1.6/bbstrader/trading/run.py +0 -131
  32. bbstrader-0.1.6/bbstrader/trading/utils.py +0 -153
  33. bbstrader-0.1.6/bbstrader/tseries.py +0 -592
  34. {bbstrader-0.1.6 → bbstrader-0.1.8}/LICENSE +0 -0
  35. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/metatrader/__init__.py +0 -0
  36. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader/models/__init__.py +0 -0
  37. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader.egg-info/dependency_links.txt +0 -0
  38. {bbstrader-0.1.6 → bbstrader-0.1.8}/bbstrader.egg-info/top_level.txt +0 -0
  39. {bbstrader-0.1.6 → bbstrader-0.1.8}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bbstrader
3
- Version: 0.1.6
3
+ Version: 0.1.8
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/
@@ -36,6 +36,9 @@ Requires-Dist: matplotlib
36
36
  Requires-Dist: filterpy
37
37
  Requires-Dist: pytest
38
38
  Requires-Dist: CurrencyConverter
39
+ Requires-Dist: tabulate
40
+ Requires-Dist: ipython
41
+ Requires-Dist: quantstats
39
42
  Requires-Dist: Metatrader5
40
43
 
41
44
  # Simplified Investment & Trading Toolkit
@@ -43,6 +46,8 @@ Requires-Dist: Metatrader5
43
46
 
44
47
  [![Documentation Status](https://readthedocs.org/projects/bbstrader/badge/?version=latest)](https://bbstrader.readthedocs.io/en/latest/?badge=latest)
45
48
 
49
+ [Dcoumentation](https://bbstrader.readthedocs.io/en/latest/index.html)
50
+
46
51
  ## Overview
47
52
 
48
53
  BBSTrader is a trading system suite developed for MetaTrader 5 (MT5) and IBKR platforms (comming soon), designed to offer a comprehensive set of tools for developping, backtesting, executing, and managing a wide array of trading strategies. With an emphasis on algorithmic and quantitative trading to provide traders with a robust platform for exploring and deploying sophisticated trading strategies.
@@ -50,7 +55,7 @@ BBSTrader is a trading system suite developed for MetaTrader 5 (MT5) and IBKR pl
50
55
  `bbstrader` is comprised of several key modules, each focus on specific aspects of trading strategy development and execution:
51
56
 
52
57
  - **Backtesting Module (btengine)** : Enables traders to rigorously test their trading strategies using historical data to evaluate performance before live deployment.
53
- - **Trading Strategies Module**: A collection of predefined trading strategies, including ARIMA+GARCH models, Kalman Filters, Ornstein-Uhlenbeck processes, and Simple Moving Averages, equipped with risk management through Hidden Markov Models.
58
+ - **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.
54
59
  - **MetaTrader5 Module (metatrader)**: Facilitates the direct execution of trading strategies on the MetaTrader 5 platform, supporting real-time trading across multiple financial instruments.
55
60
  - **Modles Module**: Serves as a framework for implementing various types of financial models (risk managment models, Machine learing models etc).
56
61
  - **Time serie Module (tseries)** designed for conducting advanced time series analysis in financial markets.
@@ -78,18 +83,22 @@ Then, you can install `bbstrader` using pip:
78
83
  pip install bbstrader
79
84
  ```
80
85
 
81
-
82
86
  ## Examples
83
87
  ### Backtesting Module
84
88
  ```python
85
- from bbstrader.btengine.backtest import run_backtest
89
+ from bbstrader.trading.strategies import test_strategy
86
90
 
87
91
  if __name__ == '__main__':
88
- # KLF IEI TLT Event Driven backtest using Kalman Filter pairs trading strategy integrating with # Hidden Markov Model (HMM) for risk management on `IEI` and `TLT`.
89
- run_backtest(test_strategy='klf')
92
+ # Run backtesting for Stock Index Short Term Buy Only Strategy
93
+ test_strategy(strategy='sistbo')
94
+
90
95
  ```
91
96
  ### Backtesting Results
92
- ![Backtesting Results](https://github.com/bbalouki/bbstrader/blob/main/assets/backtest_results.jpg?raw=true)
97
+ ![Backtesting Results 1](https://github.com/bbalouki/bbstrader/blob/main/assets/bbs_.png?raw=true)
98
+ ![Backtesting Results 2](https://github.com/bbalouki/bbstrader/blob/main/assets/qs_metrics_1.png?raw=true)
99
+ ![Backtesting Results 3](https://github.com/bbalouki/bbstrader/blob/main/assets/qs_metrics_2.png?raw=true)
100
+ ![Backtesting Results 4](https://github.com/bbalouki/bbstrader/blob/main/assets/qs_plots_1_.png?raw=true)
101
+ ![Backtesting Results 5](https://github.com/bbalouki/bbstrader/blob/main/assets/qs_plots_2_.png?raw=true)
93
102
 
94
103
  ## Customization and Contribution
95
104
 
@@ -3,6 +3,8 @@
3
3
 
4
4
  [![Documentation Status](https://readthedocs.org/projects/bbstrader/badge/?version=latest)](https://bbstrader.readthedocs.io/en/latest/?badge=latest)
5
5
 
6
+ [Dcoumentation](https://bbstrader.readthedocs.io/en/latest/index.html)
7
+
6
8
  ## Overview
7
9
 
8
10
  BBSTrader is a trading system suite developed for MetaTrader 5 (MT5) and IBKR platforms (comming soon), designed to offer a comprehensive set of tools for developping, backtesting, executing, and managing a wide array of trading strategies. With an emphasis on algorithmic and quantitative trading to provide traders with a robust platform for exploring and deploying sophisticated trading strategies.
@@ -10,7 +12,7 @@ BBSTrader is a trading system suite developed for MetaTrader 5 (MT5) and IBKR pl
10
12
  `bbstrader` is comprised of several key modules, each focus on specific aspects of trading strategy development and execution:
11
13
 
12
14
  - **Backtesting Module (btengine)** : Enables traders to rigorously test their trading strategies using historical data to evaluate performance before live deployment.
13
- - **Trading Strategies Module**: A collection of predefined trading strategies, including ARIMA+GARCH models, Kalman Filters, Ornstein-Uhlenbeck processes, and Simple Moving Averages, equipped with risk management through Hidden Markov Models.
15
+ - **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.
14
16
  - **MetaTrader5 Module (metatrader)**: Facilitates the direct execution of trading strategies on the MetaTrader 5 platform, supporting real-time trading across multiple financial instruments.
15
17
  - **Modles Module**: Serves as a framework for implementing various types of financial models (risk managment models, Machine learing models etc).
16
18
  - **Time serie Module (tseries)** designed for conducting advanced time series analysis in financial markets.
@@ -38,18 +40,22 @@ Then, you can install `bbstrader` using pip:
38
40
  pip install bbstrader
39
41
  ```
40
42
 
41
-
42
43
  ## Examples
43
44
  ### Backtesting Module
44
45
  ```python
45
- from bbstrader.btengine.backtest import run_backtest
46
+ from bbstrader.trading.strategies import test_strategy
46
47
 
47
48
  if __name__ == '__main__':
48
- # KLF IEI TLT Event Driven backtest using Kalman Filter pairs trading strategy integrating with # Hidden Markov Model (HMM) for risk management on `IEI` and `TLT`.
49
- run_backtest(test_strategy='klf')
49
+ # Run backtesting for Stock Index Short Term Buy Only Strategy
50
+ test_strategy(strategy='sistbo')
51
+
50
52
  ```
51
53
  ### Backtesting Results
52
- ![Backtesting Results](https://github.com/bbalouki/bbstrader/blob/main/assets/backtest_results.jpg?raw=true)
54
+ ![Backtesting Results 1](https://github.com/bbalouki/bbstrader/blob/main/assets/bbs_.png?raw=true)
55
+ ![Backtesting Results 2](https://github.com/bbalouki/bbstrader/blob/main/assets/qs_metrics_1.png?raw=true)
56
+ ![Backtesting Results 3](https://github.com/bbalouki/bbstrader/blob/main/assets/qs_metrics_2.png?raw=true)
57
+ ![Backtesting Results 4](https://github.com/bbalouki/bbstrader/blob/main/assets/qs_plots_1_.png?raw=true)
58
+ ![Backtesting Results 5](https://github.com/bbalouki/bbstrader/blob/main/assets/qs_plots_2_.png?raw=true)
53
59
 
54
60
  ## Customization and Contribution
55
61
 
@@ -13,5 +13,4 @@ from bbstrader import btengine
13
13
  from bbstrader import metatrader
14
14
  from bbstrader import models
15
15
  from bbstrader import trading
16
- from bbstrader import strategies
17
16
  from bbstrader import tseries
@@ -12,7 +12,6 @@ Features
12
12
 
13
13
  - **Event-Driven Architecture**: Processes market data, generates signals, executes orders, and manages portfolio updates in response to events, closely mimicking live trading environments.
14
14
  - **Historical Market Data Support**: Utilizes historical OHLCV data from CSV files, Yahoo finance and MT5 terminal allowing for the testing of strategies over various market conditions and time frames.
15
- - **Strategy Implementation Flexibility**: Abstract base classes for strategies and other components enable users to define custom trading logic and data handling processes.
16
15
  - **Performance Metrics Calculation**: Includes tools for calculating key performance indicators, such as `Sharpe Ratio`, `Sortino Ratio`, and `drawdowns`, to evaluate the effectiveness of trading strategies.
17
16
  - **Visualization**: Generates plots of the `equity curve`, `returns`, `drawdowns`, and other metrics for comprehensive strategy `performance analysis`.
18
17
 
@@ -22,29 +21,34 @@ Components
22
21
  - **Backtest**: Orchestrates the backtesting process, managing events and invoking components.
23
22
  - **Event**: Abstract class for events, with implementations for market data, signals, fill and order events.
24
23
  - **DataHandler**: Abstract class for market data handling, with an implementation for `HistoricalCSVHandler`, `MT5HistoricDataHandler`, `YFHistoricDataHandler`. We will add another data handling in the future such as MacroEconomic Data, Fundamental Data, TICK Data and Real-time Data.
25
- - **Strategy**: Abstract class for trading strategies, allowing for custom signal generation logic.
26
24
  - **Portfolio**: Manages positions and calculates performance metrics, responding to market data and signals.
27
25
  - **ExecutionHandler**: Abstract class for order execution, with a simulated execution handler provided with an implementation for `SimulatedExecutionHandler`.
28
26
  - **Performance**: Utility functions for calculating performance metrics and visualizing strategy performance.
29
27
 
30
- Examples:
31
- >>> from bbstrader.btengine import run_backtest
32
- >>> run_backtest(test_mode=True, test_strategy='ou', test_quantity=2000)
28
+ Examples
29
+ ========
33
30
 
31
+ >>> from bbstrader.btengine import run_backtest
32
+ >>> from datetime import datetime
34
33
  >>> run_backtest(
35
34
  ... symbol_list=['AAPL', 'GOOG'],
36
35
  ... start_date=datetime(2020, 1, 1),
37
- ... data_handler=CustomDataHandler(),
38
- ... strategy=MovingAverageStrategy(),
39
- ... exc_handler=CustomExecutionHandler(),
36
+ ... data_handler=DataHandler,
37
+ ... strategy=Strategy,
38
+ ... exc_handler=ExecutionHandler,
40
39
  ... initial_capital=500000.0,
41
40
  ... heartbeat=1.0
42
41
  ... )
42
+
43
+ Notes
44
+ =====
45
+
46
+ See `bbstrader.btengine.backtest.run_backtest` for more details on the backtesting process and its parameters.
43
47
  """
44
48
  from bbstrader.btengine.data import *
45
49
  from bbstrader.btengine.event import *
46
50
  from bbstrader.btengine.execution import *
47
51
  from bbstrader.btengine.performance import *
48
52
  from bbstrader.btengine.backtest import *
49
- from bbstrader.btengine.portfolio import Portfolio
50
53
  from bbstrader.btengine.strategy import Strategy
54
+ from bbstrader.btengine.portfolio import Portfolio
@@ -0,0 +1,300 @@
1
+ import pprint
2
+ import queue
3
+ import time
4
+ import yfinance as yf
5
+ from queue import Queue
6
+ from datetime import datetime
7
+ from bbstrader.btengine.data import *
8
+ from bbstrader.btengine.execution import *
9
+ from bbstrader.btengine.portfolio import Portfolio
10
+ from bbstrader.btengine.event import SignalEvent
11
+ from bbstrader.btengine.strategy import Strategy
12
+ from typing import Literal, Optional, List
13
+ from tabulate import tabulate
14
+
15
+ __all__ = [
16
+ "Backtest",
17
+ "BacktestEngine",
18
+ "run_backtest"
19
+ ]
20
+
21
+ class Backtest(object):
22
+ """
23
+ The `Backtest()` object encapsulates the event-handling logic and essentially
24
+ ties together all of the other classes.
25
+
26
+ The Backtest object is designed to carry out a nested while-loop event-driven system
27
+ in order to handle the events placed on the `Event` Queue object.
28
+ The outer while-loop is known as the "heartbeat loop" and decides the temporal resolution of
29
+ the backtesting system. In a live environment this value will be a positive number,
30
+ such as 600 seconds (every ten minutes). Thus the market data and positions
31
+ will only be updated on this timeframe.
32
+
33
+ For the backtester described here the "heartbeat" can be set to zero,
34
+ irrespective of the strategy frequency, since the data is already available by virtue of
35
+ the fact it is historical! We can run the backtest at whatever speed we like,
36
+ since the event-driven system is agnostic to when the data became available,
37
+ so long as it has an associated timestamp.
38
+
39
+ The inner while-loop actually processes the signals and sends them to the correct
40
+ component depending upon the event type. Thus the Event Queue is continually being
41
+ populated and depopulated with events. This is what it means for a system to be event-driven.
42
+
43
+ The initialisation of the Backtest object requires the full `symbol list` of traded symbols,
44
+ the `initial capital`, the `heartbeat` time in milliseconds, the `start datetime` stamp
45
+ of the backtest as well as the `DataHandler`, `ExecutionHandler`, `Strategy` objects
46
+ and additionnal `kwargs` based on the `ExecutionHandler`, the `DataHandler`, and the `Strategy` used.
47
+
48
+ A Queue is used to hold the events. The signals, orders and fills are counted.
49
+ For a `MarketEvent`, the `Strategy` object is told to recalculate new signals,
50
+ while the `Portfolio` object is told to reindex the time. If a `SignalEvent`
51
+ object is received the `Portfolio` is told to handle the new signal and convert it into a
52
+ set of `OrderEvents`, if appropriate. If an `OrderEvent` is received the `ExecutionHandler`
53
+ is sent the order to be transmitted to the broker (if in a real trading setting).
54
+ Finally, if a `FillEvent` is received, the Portfolio will update itself to be aware of
55
+ the new positions.
56
+
57
+ """
58
+
59
+ def __init__(
60
+ self,
61
+ symbol_list: List[str],
62
+ initial_capital: float,
63
+ heartbeat: float,
64
+ start_date: datetime,
65
+ data_handler: DataHandler,
66
+ execution_handler: ExecutionHandler,
67
+ strategy: Strategy,
68
+ /,
69
+ **kwargs
70
+ ):
71
+ """
72
+ Initialises the backtest.
73
+
74
+ Args:
75
+ symbol_list (List[str]): The list of symbol strings.
76
+ intial_capital (float): The starting capital for the portfolio.
77
+ heartbeat (float): Backtest "heartbeat" in seconds
78
+ start_date (datetime): The start datetime of the strategy.
79
+ data_handler (DataHandler) : Handles the market data feed.
80
+ execution_handler (ExecutionHandler) : Handles the orders/fills for trades.
81
+ strategy (Strategy): Generates signals based on market data.
82
+ kwargs : Additional parameters based on the `ExecutionHandler`,
83
+ the `DataHandler`, the `Strategy` used and the `Portfolio`.
84
+ """
85
+ self.symbol_list = symbol_list
86
+ self.initial_capital = initial_capital
87
+ self.heartbeat = heartbeat
88
+ self.start_date = start_date
89
+
90
+ self.dh_cls = data_handler
91
+ self.eh_cls = execution_handler
92
+ self.strategy_cls = strategy
93
+ self.kwargs = kwargs
94
+
95
+ self.events = queue.Queue()
96
+
97
+ self.signals = 0
98
+ self.orders = 0
99
+ self.fills = 0
100
+
101
+ self._generate_trading_instances()
102
+ self.show_equity = kwargs.get("show_equity", False)
103
+
104
+ def _generate_trading_instances(self):
105
+ """
106
+ Generates the trading instance objects from
107
+ their class types.
108
+ """
109
+ print(
110
+ f"\nStarting Backtest on {self.symbol_list} "
111
+ f"with ${self.initial_capital} Initial Capital\n"
112
+ )
113
+ self.data_handler: DataHandler = self.dh_cls(
114
+ self.events, self.symbol_list, **self.kwargs
115
+ )
116
+ self.strategy: Strategy = self.strategy_cls(
117
+ bars=self.data_handler, events=self.events, **self.kwargs
118
+ )
119
+ self.portfolio = Portfolio(
120
+ self.data_handler,
121
+ self.events,
122
+ self.start_date,
123
+ self.initial_capital, **self.kwargs
124
+ )
125
+ self.execution_handler: ExecutionHandler = self.eh_cls(
126
+ self.events, **self.kwargs)
127
+
128
+ def _run_backtest(self):
129
+ """
130
+ Executes the backtest.
131
+ """
132
+ i = 0
133
+ while True:
134
+ i += 1
135
+ print(i)
136
+ # Update the market bars
137
+ if self.data_handler.continue_backtest == True:
138
+ self.data_handler.update_bars()
139
+ else:
140
+ break
141
+
142
+ # Handle the events
143
+ while True:
144
+ try:
145
+ event = self.events.get(False)
146
+ except queue.Empty:
147
+ break
148
+ else:
149
+ if event is not None:
150
+ if event.type == 'MARKET':
151
+ self.strategy.calculate_signals(event)
152
+ self.portfolio.update_timeindex(event)
153
+
154
+ elif event.type == 'SIGNAL':
155
+ self.signals += 1
156
+ self.portfolio.update_signal(event)
157
+
158
+ elif event.type == 'ORDER':
159
+ self.orders += 1
160
+ self.execution_handler.execute_order(event)
161
+
162
+ elif event.type == 'FILL':
163
+ self.fills += 1
164
+ self.portfolio.update_fill(event)
165
+
166
+ time.sleep(self.heartbeat)
167
+
168
+ def _output_performance(self):
169
+ """
170
+ Outputs the strategy performance from the backtest.
171
+ """
172
+ self.portfolio.create_equity_curve_dataframe()
173
+
174
+ print("\nCreating summary stats...")
175
+ stats = self.portfolio.output_summary_stats()
176
+ print("[======= Summary Stats =======]")
177
+ stat2 = {}
178
+ stat2['Signals'] = self.signals
179
+ stat2['Orders'] = self.orders
180
+ stat2['Fills'] = self.fills
181
+ stats.extend(stat2.items())
182
+ print(
183
+ tabulate(
184
+ stats,
185
+ headers=["Metric", "Value"],
186
+ tablefmt="outline"),
187
+ "\n"
188
+ )
189
+
190
+ if self.show_equity:
191
+ print("\nCreating equity curve...")
192
+ print("\n[======= EQUITY CURVE =======]")
193
+ print(
194
+ tabulate(
195
+ self.portfolio.equity_curve.tail(10),
196
+ headers="keys",
197
+ tablefmt="outline"),
198
+ "\n"
199
+ )
200
+
201
+ def simulate_trading(self):
202
+ """
203
+ Simulates the backtest and outputs portfolio performance.
204
+ """
205
+ self._run_backtest()
206
+ self._output_performance()
207
+
208
+ BacktestEngine = Backtest
209
+
210
+ def run_backtest(
211
+ symbol_list: List[str],
212
+ start_date: datetime,
213
+ data_handler: DataHandler,
214
+ strategy: Strategy,
215
+ exc_handler: Optional[ExecutionHandler] = None,
216
+ initial_capital: float = 100000.0,
217
+ heartbeat: float = 0.0,
218
+ **kwargs
219
+ ):
220
+ """
221
+ Runs a backtest simulation based on a `DataHandler`, `Strategy`, and `ExecutionHandler`.
222
+
223
+ Args:
224
+ symbol_list (List[str]): List of symbol strings for the assets to be backtested.
225
+
226
+ start_date (datetime): Start date of the backtest.
227
+
228
+ data_handler (DataHandler): An instance of the `DataHandler` class, responsible for managing
229
+ and processing market data. Available options include `HistoricCSVDataHandler`,
230
+ `MT5HistoricDataHandler`, and `YFHistoricDataHandler`. Ensure that the `DataHandler`
231
+ instance is initialized before passing it to the function.
232
+
233
+ strategy (Strategy): The trading strategy to be employed during the backtest.
234
+ The strategy must be an instance of `Strategy` and should include the following attributes:
235
+ - `bars` (DataHandler): The `DataHandler` instance for the strategy.
236
+ - `events` (Queue): Queue instance for managing events.
237
+ - `symbol_list` (List[str]): List of symbols to trade.
238
+ - `mode` (str): 'live' or 'backtest'.
239
+
240
+ Additional parameters specific to the strategy should be passed in `**kwargs`.
241
+ The strategy class must implement a `calculate_signals` method to generate `SignalEvent`.
242
+
243
+ exc_handler (ExecutionHandler, optional): The execution handler for managing order executions.
244
+ If not provided, a `SimulatedExecutionHandler` will be used by default. This handler must
245
+ implement an `execute_order` method to process `OrderEvent` in the `Backtest` class.
246
+
247
+ initial_capital (float, optional): The initial capital for the portfolio in the backtest.
248
+ Default is 100,000.
249
+
250
+ heartbeat (float, optional): Time delay (in seconds) between iterations of the event-driven
251
+ backtest loop. Default is 0.0, allowing the backtest to run as fast as possible. This could
252
+ also be used as a time frame in live trading (e.g., 1m, 5m, 15m) with a live `DataHandler`.
253
+
254
+ **kwargs: Additional parameters passed to the `Backtest` instance, which may include strategy-specific,
255
+ data handler, portfolio, or execution handler options.
256
+
257
+ Notes:
258
+ This function generates three outputs:
259
+ - A performance summary saved as an HTML file.
260
+ - An equity curve of the portfolio saved as a CSV file.
261
+ - Monthly returns saved as a PNG image.
262
+
263
+ Example:
264
+ >>> from bbstrader.trading.strategies import StockIndexSTBOTrading
265
+ >>> from bbstrader.metatrader.utils import config_logger
266
+ >>> from bbstrader.datahandlers import MT5HistoricDataHandler
267
+ >>> from bbstrader.execution import MT5ExecutionHandler
268
+ >>> from datetime import datetime
269
+ >>>
270
+ >>> logger = config_logger('index_trade.log', console_log=True)
271
+ >>> symbol_list = ['[SP500]', 'GERMANY40', '[DJI30]', '[NQ100]']
272
+ >>> start = datetime(2010, 6, 1, 2, 0, 0)
273
+ >>> kwargs = {
274
+ ... 'expected_returns': {'[NQ100]': 1.5, '[SP500]': 1.5, '[DJI30]': 1.0, 'GERMANY40': 1.0},
275
+ ... 'quantities': {'[NQ100]': 15, '[SP500]': 30, '[DJI30]': 5, 'GERMANY40': 10},
276
+ ... 'max_trades': {'[NQ100]': 3, '[SP500]': 3, '[DJI30]': 3, 'GERMANY40': 3},
277
+ ... 'mt5_start': start,
278
+ ... 'time_frame': '15m',
279
+ ... 'strategy_name': 'SISTBO',
280
+ ... }
281
+ >>> run_backtest(
282
+ ... symbol_list=symbol_list,
283
+ ... start_date=start,
284
+ ... data_handler=MT5HistoricDataHandler(),
285
+ ... strategy=StockIndexSTBOTrading(),
286
+ ... exc_handler=MT5ExecutionHandler(),
287
+ ... initial_capital=100000.0,
288
+ ... heartbeat=0.0,
289
+ ... **kwargs
290
+ ... )
291
+ """
292
+ if exc_handler is None:
293
+ execution_handler = SimulatedExecutionHandler
294
+ else:
295
+ execution_handler = exc_handler
296
+ engine = BacktestEngine(
297
+ symbol_list, initial_capital, heartbeat, start_date,
298
+ data_handler, execution_handler, strategy, **kwargs
299
+ )
300
+ engine.simulate_trading()
@@ -360,10 +360,12 @@ class YFHistoricDataHandler(BaseCSVDataHandler):
360
360
 
361
361
 
362
362
  # TODO # Get data from EODHD
363
+ # https://eodhd.com/
363
364
  class EODHDHistoricDataHandler(BaseCSVDataHandler):
364
365
  ...
365
366
 
366
- # TODO # Get data from FinancialModelingPrep ()
367
+ # TODO # Get data from FMP using Financialtoolkit API
368
+ # https://github.com/bbalouki/FinanceToolkit
367
369
  class FMPHistoricDataHandler(BaseCSVDataHandler):
368
370
  ...
369
371
 
@@ -54,9 +54,10 @@ class SignalEvent(Event):
54
54
  strategy_id: int,
55
55
  symbol: str,
56
56
  datetime: datetime,
57
- signal_type: str,
57
+ signal_type: Literal['LONG', 'SHORT', 'EXIT'],
58
58
  quantity: int | float = 100,
59
- strength: int | float = 1.0
59
+ strength: int | float = 1.0,
60
+ price: int | float = None
60
61
  ):
61
62
  """
62
63
  Initialises the SignalEvent.
@@ -67,10 +68,11 @@ class SignalEvent(Event):
67
68
 
68
69
  symbol (str): The ticker symbol, e.g. 'GOOG'.
69
70
  datetime (datetime): The timestamp at which the signal was generated.
70
- signal_type (str): 'LONG' or 'SHORT'.
71
+ signal_type (str): 'LONG' or 'SHORT' or 'EXIT'.
71
72
  quantity (int | float): An optional integer (or float) representing the order size.
72
73
  strength (int | float): An adjustment factor "suggestion" used to scale
73
74
  quantity at the portfolio level. Useful for pairs strategies.
75
+ price (int | float): An optional price to be used when the signal is generated.
74
76
  """
75
77
  self.type = 'SIGNAL'
76
78
  self.strategy_id = strategy_id
@@ -79,6 +81,7 @@ class SignalEvent(Event):
79
81
  self.signal_type = signal_type
80
82
  self.quantity = quantity
81
83
  self.strength = strength
84
+ self.price = price
82
85
 
83
86
 
84
87
  class OrderEvent(Event):
@@ -96,9 +99,10 @@ class OrderEvent(Event):
96
99
 
97
100
  def __init__(self,
98
101
  symbol: str,
99
- order_type: str,
102
+ order_type: Literal['MKT', 'LMT'],
100
103
  quantity: int | float,
101
- direction: str
104
+ direction: Literal['BUY', 'SELL'],
105
+ price: int | float = None
102
106
  ):
103
107
  """
104
108
  Initialises the order type, setting whether it is
@@ -110,20 +114,22 @@ class OrderEvent(Event):
110
114
  order_type (str): 'MKT' or 'LMT' for Market or Limit.
111
115
  quantity (int | float): Non-negative number for quantity.
112
116
  direction (str): 'BUY' or 'SELL' for long or short.
117
+ price (int | float): The price at which to order.
113
118
  """
114
119
  self.type = 'ORDER'
115
120
  self.symbol = symbol
116
121
  self.order_type = order_type
117
122
  self.quantity = quantity
118
123
  self.direction = direction
124
+ self.price = price
119
125
 
120
126
  def print_order(self):
121
127
  """
122
128
  Outputs the values within the Order.
123
129
  """
124
130
  print(
125
- "Order: Symbol=%s, Type=%s, Quantity=%s, Direction=%s" %
126
- (self.symbol, self.order_type, self.quantity, self.direction)
131
+ "Order: Symbol=%s, Type=%s, Quantity=%s, Direction=%s, Price=%s" %
132
+ (self.symbol, self.order_type, self.quantity, self.direction, self.price)
127
133
  )
128
134
 
129
135
 
@@ -151,7 +157,7 @@ class FillEvent(Event):
151
157
  symbol: str,
152
158
  exchange: str,
153
159
  quantity: int | float,
154
- direction: Literal['LONG', 'SHORT', 'EXIT'],
160
+ direction: Literal['BUY', 'SELL'],
155
161
  fill_cost: int | float | None,
156
162
  commission: float | None = None
157
163
  ):
@@ -170,7 +176,7 @@ class FillEvent(Event):
170
176
  exchange (str): The exchange where the order was filled.
171
177
  quantity (int | float): The filled quantity.
172
178
  direction (str): The direction of fill `('LONG', 'SHORT', 'EXIT')`
173
- fill_cost (int | float): The holdings value in dollars.
179
+ fill_cost (int | float): Price of the shares when filled.
174
180
  commission (float | None): An optional commission sent from IB.
175
181
  """
176
182
  self.type = 'FILL'