quantex 0.5.1__tar.gz → 0.5.2__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.
- {quantex-0.5.1 → quantex-0.5.2}/PKG-INFO +1 -1
- {quantex-0.5.1 → quantex-0.5.2}/pyproject.toml +1 -1
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/backtester/reports.py +47 -42
- {quantex-0.5.1 → quantex-0.5.2}/LICENSE.md +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/README.md +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/__init__.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/backtester/__init__.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/backtester/backtester.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/backtester/constants.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/backtester/data_splits.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/backtester/metrics.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/backtester/montecarlo.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/backtester/parallel.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/backtester/walk_forward.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/broker/__init__.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/broker/broker.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/broker/types.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/datasource.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/helpers.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/indicators.py +0 -0
- {quantex-0.5.1 → quantex-0.5.2}/src/quantex/strategy.py +0 -0
|
@@ -6,6 +6,8 @@ import numpy as np
|
|
|
6
6
|
import pandas as pd
|
|
7
7
|
from matplotlib import pyplot as plt
|
|
8
8
|
|
|
9
|
+
from ..broker.types import Order
|
|
10
|
+
|
|
9
11
|
|
|
10
12
|
@dataclass
|
|
11
13
|
class OptimizationResult:
|
|
@@ -58,7 +60,7 @@ class BacktestReport:
|
|
|
58
60
|
starting_cash: np.float64
|
|
59
61
|
final_cash: np.float64
|
|
60
62
|
PnlRecord: pd.Series
|
|
61
|
-
orders: list
|
|
63
|
+
orders: list[Order]
|
|
62
64
|
tradeRecord: list[np.float64]
|
|
63
65
|
margin_call_events: list[dict] | None = None
|
|
64
66
|
data: pd.DataFrame = field(default_factory=lambda: pd.DataFrame())
|
|
@@ -215,59 +217,61 @@ class BacktestReport:
|
|
|
215
217
|
if end_date is not None:
|
|
216
218
|
data = data[data.index <= end_date]
|
|
217
219
|
|
|
218
|
-
# Create marker series
|
|
220
|
+
# Create marker series with the same index as the data
|
|
219
221
|
buy_signal = pd.Series(index=data.index, dtype=float)
|
|
220
222
|
sell_signal = pd.Series(index=data.index, dtype=float)
|
|
221
223
|
|
|
222
|
-
# Track positions to determine entries and exits
|
|
223
|
-
# Buy orders that are not reduce_only are entries
|
|
224
|
-
# Sell orders that are reduce_only are exits (closing long positions)
|
|
225
|
-
# Similarly for sells: Sell orders that are not reduce_only are entries
|
|
226
|
-
# Buy orders that are reduce_only are exits (closing short positions)
|
|
227
|
-
|
|
228
224
|
for order in self.orders:
|
|
229
225
|
timestamp = order.timestamp
|
|
230
226
|
|
|
231
|
-
# Only
|
|
227
|
+
# Only set signal if timestamp exists in the data index
|
|
232
228
|
if timestamp not in data.index:
|
|
233
229
|
continue
|
|
234
230
|
|
|
235
|
-
|
|
236
|
-
if price is None:
|
|
237
|
-
continue
|
|
238
|
-
|
|
231
|
+
# Set the signal at the order timestamp
|
|
239
232
|
if order.side == OrderSide.BUY:
|
|
240
|
-
|
|
241
|
-
# Buy entry (opening long position)
|
|
242
|
-
buy_signal.loc[timestamp] = price
|
|
243
|
-
else:
|
|
244
|
-
# Buy to close short position (exit)
|
|
245
|
-
sell_signal.loc[timestamp] = price
|
|
233
|
+
buy_signal.loc[timestamp] = data.loc[timestamp, 'Close'] # type: ignore
|
|
246
234
|
else: # OrderSide.SELL
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
sell_signal.loc[timestamp] = price
|
|
235
|
+
sell_signal.loc[timestamp] = data.loc[timestamp, 'Close'] # type: ignore
|
|
236
|
+
|
|
237
|
+
# If no trades to plot and no data, raise an error
|
|
238
|
+
if data.empty:
|
|
239
|
+
raise ValueError("No data available to plot. Check your date range.")
|
|
253
240
|
|
|
254
|
-
#
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
)
|
|
270
|
-
|
|
241
|
+
# Check if there are actual trade markers (non-NaN values)
|
|
242
|
+
has_buy_signals = not buy_signal.dropna().empty
|
|
243
|
+
has_sell_signals = not sell_signal.dropna().empty
|
|
244
|
+
|
|
245
|
+
# Build addplot list with markers (only if we have data points)
|
|
246
|
+
apds = []
|
|
247
|
+
if has_buy_signals:
|
|
248
|
+
apds.append(
|
|
249
|
+
mpf.make_addplot(
|
|
250
|
+
buy_signal,
|
|
251
|
+
type="scatter",
|
|
252
|
+
marker="^",
|
|
253
|
+
markersize=120,
|
|
254
|
+
color="green",
|
|
255
|
+
)
|
|
256
|
+
)
|
|
257
|
+
if has_sell_signals:
|
|
258
|
+
apds.append(
|
|
259
|
+
mpf.make_addplot(
|
|
260
|
+
sell_signal,
|
|
261
|
+
type="scatter",
|
|
262
|
+
marker="v",
|
|
263
|
+
markersize=120,
|
|
264
|
+
color="red",
|
|
265
|
+
)
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
# If no trades found in the date range, warn the user
|
|
269
|
+
if not apds:
|
|
270
|
+
import warnings
|
|
271
|
+
warnings.warn(
|
|
272
|
+
"No trades found in the specified date range. "
|
|
273
|
+
"Plotting price data without trade markers."
|
|
274
|
+
)
|
|
271
275
|
|
|
272
276
|
# Generate default title if not provided
|
|
273
277
|
if title is None:
|
|
@@ -282,6 +286,7 @@ class BacktestReport:
|
|
|
282
286
|
figsize=figsize,
|
|
283
287
|
style=style,
|
|
284
288
|
title=title,
|
|
289
|
+
warn_too_much_data=len(data) + 5
|
|
285
290
|
)
|
|
286
291
|
|
|
287
292
|
def __str__(self) -> str:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|