quantbt-engine 1.0.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.
Files changed (133) hide show
  1. quantbt/__init__.py +862 -0
  2. quantbt/adapters/__init__.py +5 -0
  3. quantbt/adapters/nautilus/__init__.py +42 -0
  4. quantbt/adapters/nautilus/_dependency.py +53 -0
  5. quantbt/adapters/nautilus/backend.py +639 -0
  6. quantbt/adapters/nautilus/instruments.py +275 -0
  7. quantbt/adapters/nautilus/options.py +465 -0
  8. quantbt/adapters/nautilus/reports.py +231 -0
  9. quantbt/backends/__init__.py +29 -0
  10. quantbt/backends/_native_event_rust.py +2168 -0
  11. quantbt/backends/native_event.py +5048 -0
  12. quantbt/backends/native_option.py +796 -0
  13. quantbt/backends/native_portfolio.py +928 -0
  14. quantbt/backends/native_vectorized.py +1299 -0
  15. quantbt/backtester.py +485 -0
  16. quantbt/benchmarks/__init__.py +1 -0
  17. quantbt/benchmarks/compare_phase9_parity.py +302 -0
  18. quantbt/benchmarks/gamma_scalping_backtestsample.py +802 -0
  19. quantbt/benchmarks/profile_phase7.py +415 -0
  20. quantbt/benchmarks/run_arbitrage_phase_e.py +160 -0
  21. quantbt/benchmarks/run_optimization_overhead.py +195 -0
  22. quantbt/benchmarks/run_options_engine.py +272 -0
  23. quantbt/benchmarks/run_pct_equity_nautilus_smoke.py +227 -0
  24. quantbt/benchmarks/run_phase12_arbitrage_cert.py +402 -0
  25. quantbt/benchmarks/run_phase12_benchmark_nautilus_cert.py +430 -0
  26. quantbt/benchmarks/run_phase13_portfolio_report.py +97 -0
  27. quantbt/benchmarks/run_phase13_wfo_cache.py +162 -0
  28. quantbt/benchmarks/run_phase14_service_loop.py +694 -0
  29. quantbt/benchmarks/run_phase15a_nautilus_certification.py +514 -0
  30. quantbt/benchmarks/run_phase15b_synthetic_depth.py +175 -0
  31. quantbt/benchmarks/run_phase16_performance_debt.py +389 -0
  32. quantbt/benchmarks/run_phase30e_reactive_runner.py +161 -0
  33. quantbt/benchmarks/run_phase31_intrabar.py +441 -0
  34. quantbt/benchmarks/run_phase34a_native_event_memory.py +179 -0
  35. quantbt/benchmarks/run_phase34b_native_event_prepared_score.py +173 -0
  36. quantbt/benchmarks/run_phase34c_native_event_single_pass.py +176 -0
  37. quantbt/benchmarks/run_phase7.py +654 -0
  38. quantbt/benchmarks/run_portfolio_real_parity.py +537 -0
  39. quantbt/core/__init__.py +323 -0
  40. quantbt/core/arbitrage.py +767 -0
  41. quantbt/core/basket.py +234 -0
  42. quantbt/core/certification.py +274 -0
  43. quantbt/core/constraints.py +155 -0
  44. quantbt/core/engine.py +1144 -0
  45. quantbt/core/event.py +869 -0
  46. quantbt/core/execution_contract.py +197 -0
  47. quantbt/core/execution_depth.py +613 -0
  48. quantbt/core/intrabar_kernel.py +1906 -0
  49. quantbt/core/intrabar_reference.py +907 -0
  50. quantbt/core/intrabar_session.py +156 -0
  51. quantbt/core/market_tape.py +480 -0
  52. quantbt/core/native_event_capabilities.py +121 -0
  53. quantbt/core/native_event_parity.py +336 -0
  54. quantbt/core/order_compiler.py +422 -0
  55. quantbt/core/orders.py +319 -0
  56. quantbt/core/portfolio.py +392 -0
  57. quantbt/core/preprocessor.py +256 -0
  58. quantbt/core/reactive.py +173 -0
  59. quantbt/core/results.py +341 -0
  60. quantbt/core/schema.py +211 -0
  61. quantbt/core/scopes.py +96 -0
  62. quantbt/core/structured_orders.py +378 -0
  63. quantbt/core/types.py +87 -0
  64. quantbt/core/vectorized.py +203 -0
  65. quantbt/endpoint.py +4465 -0
  66. quantbt/engines.py +1014 -0
  67. quantbt/metrics/__init__.py +45 -0
  68. quantbt/metrics/options_analytics.py +46 -0
  69. quantbt/metrics/performance.py +541 -0
  70. quantbt/optimization/__init__.py +94 -0
  71. quantbt/optimization/callbacks.py +116 -0
  72. quantbt/optimization/candidate_selection.py +397 -0
  73. quantbt/optimization/config.py +84 -0
  74. quantbt/optimization/constraints.py +22 -0
  75. quantbt/optimization/evaluator.py +21 -0
  76. quantbt/optimization/evaluators/__init__.py +32 -0
  77. quantbt/optimization/evaluators/arbitrage.py +22 -0
  78. quantbt/optimization/evaluators/generic.py +34 -0
  79. quantbt/optimization/evaluators/grid_dca.py +22 -0
  80. quantbt/optimization/evaluators/intrabar.py +54 -0
  81. quantbt/optimization/evaluators/native_event.py +51 -0
  82. quantbt/optimization/evaluators/options.py +22 -0
  83. quantbt/optimization/evaluators/portfolio.py +42 -0
  84. quantbt/optimization/evaluators/signal.py +43 -0
  85. quantbt/optimization/multiseed.py +176 -0
  86. quantbt/optimization/objectives.py +221 -0
  87. quantbt/optimization/optimizer.py +500 -0
  88. quantbt/optimization/result.py +80 -0
  89. quantbt/optimization/samplers.py +84 -0
  90. quantbt/optimization/space.py +223 -0
  91. quantbt/options/__init__.py +215 -0
  92. quantbt/options/cache.py +116 -0
  93. quantbt/options/conventions.py +158 -0
  94. quantbt/options/data.py +177 -0
  95. quantbt/options/execution.py +600 -0
  96. quantbt/options/fees.py +135 -0
  97. quantbt/options/greeks.py +173 -0
  98. quantbt/options/hedging.py +232 -0
  99. quantbt/options/iv.py +188 -0
  100. quantbt/options/ledger.py +263 -0
  101. quantbt/options/lifecycle.py +94 -0
  102. quantbt/options/margin.py +311 -0
  103. quantbt/options/packages.py +147 -0
  104. quantbt/options/pricing.py +191 -0
  105. quantbt/options/schema.py +227 -0
  106. quantbt/options/selectors.py +281 -0
  107. quantbt/options/strategy.py +249 -0
  108. quantbt/options/surface.py +142 -0
  109. quantbt/options/tape.py +226 -0
  110. quantbt/options/templates/__init__.py +33 -0
  111. quantbt/options/templates/packages.py +354 -0
  112. quantbt/portfolio.py +606 -0
  113. quantbt/py.typed +1 -0
  114. quantbt/reporting/__init__.py +38 -0
  115. quantbt/reporting/arbitrage_audit.py +211 -0
  116. quantbt/reporting/nautilus_bundle.py +758 -0
  117. quantbt/reporting/nautilus_certification.py +226 -0
  118. quantbt/reporting/nautilus_diagnostics.py +225 -0
  119. quantbt/reporting/parity.py +496 -0
  120. quantbt/reporting/portfolio_audit.py +206 -0
  121. quantbt/reporting/portfolio_nautilus.py +140 -0
  122. quantbt/sizing/__init__.py +3 -0
  123. quantbt/sizing/fast.py +67 -0
  124. quantbt/sizing/modes.py +162 -0
  125. quantbt/viz/__init__.py +4 -0
  126. quantbt/viz/plots.py +310 -0
  127. quantbt/viz/themes.py +102 -0
  128. quantbt/walkforward.py +3136 -0
  129. quantbt_engine-1.0.7.dist-info/METADATA +891 -0
  130. quantbt_engine-1.0.7.dist-info/RECORD +133 -0
  131. quantbt_engine-1.0.7.dist-info/WHEEL +5 -0
  132. quantbt_engine-1.0.7.dist-info/licenses/LICENSE +21 -0
  133. quantbt_engine-1.0.7.dist-info/top_level.txt +1 -0
@@ -0,0 +1,275 @@
1
+ """
2
+ Data and instrument helpers for NautilusTrader adapter.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ from dataclasses import dataclass
8
+ from decimal import Decimal
9
+
10
+ import pandas as pd
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class BinancePerpSpec:
15
+ raw_symbol: str
16
+ base_currency: str
17
+ price_precision: int
18
+ price_increment: str
19
+ size_precision: int
20
+ size_increment: str
21
+ max_quantity: str
22
+ min_quantity: str
23
+ max_price: str
24
+ min_price: str
25
+ margin_init: str = "0.0500"
26
+ margin_maint: str = "0.0250"
27
+ maker_fee: str = "0.0002"
28
+ taker_fee: str = "0.0004"
29
+
30
+
31
+ SUPPORTED_BINANCE_PERP_SPECS = {
32
+ "BTCUSDT": BinancePerpSpec(
33
+ raw_symbol="BTCUSDT",
34
+ base_currency="BTC",
35
+ price_precision=1,
36
+ price_increment="0.1",
37
+ size_precision=3,
38
+ size_increment="0.001",
39
+ max_quantity="1000.000",
40
+ min_quantity="0.001",
41
+ max_price="809484.0",
42
+ min_price="261.1",
43
+ maker_fee="0.000200",
44
+ taker_fee="0.000180",
45
+ ),
46
+ "ETHUSDT": BinancePerpSpec(
47
+ raw_symbol="ETHUSDT",
48
+ base_currency="ETH",
49
+ price_precision=2,
50
+ price_increment="0.01",
51
+ size_precision=3,
52
+ size_increment="0.001",
53
+ max_quantity="10000.000",
54
+ min_quantity="0.001",
55
+ max_price="152588.43",
56
+ min_price="29.91",
57
+ ),
58
+ "BNBUSDT": BinancePerpSpec(
59
+ raw_symbol="BNBUSDT",
60
+ base_currency="BNB",
61
+ price_precision=2,
62
+ price_increment="0.01",
63
+ size_precision=2,
64
+ size_increment="0.01",
65
+ max_quantity="100000.00",
66
+ min_quantity="0.01",
67
+ max_price="100000.00",
68
+ min_price="1.00",
69
+ ),
70
+ "SOLUSDT": BinancePerpSpec(
71
+ raw_symbol="SOLUSDT",
72
+ base_currency="SOL",
73
+ price_precision=3,
74
+ price_increment="0.001",
75
+ size_precision=2,
76
+ size_increment="0.01",
77
+ max_quantity="100000.00",
78
+ min_quantity="0.01",
79
+ max_price="100000.000",
80
+ min_price="0.100",
81
+ ),
82
+ "DOGEUSDT": BinancePerpSpec(
83
+ raw_symbol="DOGEUSDT",
84
+ base_currency="DOGE",
85
+ price_precision=5,
86
+ price_increment="0.00001",
87
+ size_precision=0,
88
+ size_increment="1",
89
+ max_quantity="100000000",
90
+ min_quantity="1",
91
+ max_price="1000.00000",
92
+ min_price="0.00010",
93
+ ),
94
+ "ARBUSDT": BinancePerpSpec(
95
+ raw_symbol="ARBUSDT",
96
+ base_currency="ARB",
97
+ price_precision=4,
98
+ price_increment="0.0001",
99
+ size_precision=1,
100
+ size_increment="0.1",
101
+ max_quantity="10000000.0",
102
+ min_quantity="0.1",
103
+ max_price="10000.0000",
104
+ min_price="0.0001",
105
+ ),
106
+ "LINKUSDT": BinancePerpSpec(
107
+ raw_symbol="LINKUSDT",
108
+ base_currency="LINK",
109
+ price_precision=3,
110
+ price_increment="0.001",
111
+ size_precision=2,
112
+ size_increment="0.01",
113
+ max_quantity="1000000.00",
114
+ min_quantity="0.01",
115
+ max_price="100000.000",
116
+ min_price="0.001",
117
+ ),
118
+ }
119
+
120
+ _ALIASES = {
121
+ "BTC": "BTCUSDT",
122
+ "BTCUSDT-PERP": "BTCUSDT",
123
+ "BTCUSDT-PERP.BINANCE": "BTCUSDT",
124
+ "ETH": "ETHUSDT",
125
+ "ETHUSDT-PERP": "ETHUSDT",
126
+ "ETHUSDT-PERP.BINANCE": "ETHUSDT",
127
+ "BNB": "BNBUSDT",
128
+ "BNBUSDT-PERP": "BNBUSDT",
129
+ "BNBUSDT-PERP.BINANCE": "BNBUSDT",
130
+ "SOL": "SOLUSDT",
131
+ "SOLUSDT-PERP": "SOLUSDT",
132
+ "SOLUSDT-PERP.BINANCE": "SOLUSDT",
133
+ "DOGE": "DOGEUSDT",
134
+ "DOGEUSDT-PERP": "DOGEUSDT",
135
+ "DOGEUSDT-PERP.BINANCE": "DOGEUSDT",
136
+ "ARB": "ARBUSDT",
137
+ "ARP": "ARBUSDT",
138
+ "ARBUSDT-PERP": "ARBUSDT",
139
+ "ARBUSDT-PERP.BINANCE": "ARBUSDT",
140
+ "ARPUSDT": "ARBUSDT",
141
+ "ARPUSDT-PERP": "ARBUSDT",
142
+ "ARPUSDT-PERP.BINANCE": "ARBUSDT",
143
+ "LINK": "LINKUSDT",
144
+ "LINKUSDT-PERP": "LINKUSDT",
145
+ "LINKUSDT-PERP.BINANCE": "LINKUSDT",
146
+ }
147
+
148
+ _TIMEFRAME_MAP = {
149
+ "1min": "1-MINUTE",
150
+ "1m": "1-MINUTE",
151
+ "5min": "5-MINUTE",
152
+ "5m": "5-MINUTE",
153
+ "15min": "15-MINUTE",
154
+ "15m": "15-MINUTE",
155
+ "30min": "30-MINUTE",
156
+ "30m": "30-MINUTE",
157
+ "1h": "1-HOUR",
158
+ "2h": "2-HOUR",
159
+ "4h": "4-HOUR",
160
+ "6h": "6-HOUR",
161
+ "12h": "12-HOUR",
162
+ "1d": "1-DAY",
163
+ "1w": "1-WEEK",
164
+ }
165
+
166
+
167
+ def supported_binance_perpetuals() -> list[str]:
168
+ return [f"{symbol}-PERP.BINANCE" for symbol in SUPPORTED_BINANCE_PERP_SPECS]
169
+
170
+
171
+ def normalize_binance_perp_symbol(instrument_id: str) -> str:
172
+ key = str(instrument_id).upper().strip().replace("/", "")
173
+ if key in _ALIASES:
174
+ return _ALIASES[key]
175
+ if key.endswith(".BINANCE"):
176
+ key = key.removesuffix(".BINANCE")
177
+ if key.endswith("-PERP"):
178
+ key = key.removesuffix("-PERP")
179
+ if key in SUPPORTED_BINANCE_PERP_SPECS:
180
+ return key
181
+ raise ValueError(
182
+ f"Unsupported Nautilus Binance perpetual {instrument_id!r}. "
183
+ f"Supported: {', '.join(supported_binance_perpetuals())}"
184
+ )
185
+
186
+
187
+ def make_binance_perpetual(instrument_id: str, nt):
188
+ """
189
+ Return a Nautilus Binance USDT perpetual test/synthetic instrument.
190
+
191
+ BTC and ETH use Nautilus test-kit providers. Other liquid symbols are
192
+ synthetic `CryptoPerpetual` definitions suitable for external OHLCV bars.
193
+ """
194
+ raw_symbol = normalize_binance_perp_symbol(instrument_id)
195
+ if raw_symbol == "BTCUSDT":
196
+ return nt.TestInstrumentProvider.btcusdt_perp_binance()
197
+ if raw_symbol == "ETHUSDT":
198
+ return nt.TestInstrumentProvider.ethusdt_perp_binance()
199
+
200
+ from nautilus_trader.model import currencies
201
+ from nautilus_trader.model.identifiers import InstrumentId, Symbol, Venue
202
+ from nautilus_trader.model.instruments import CryptoPerpetual
203
+ from nautilus_trader.model.objects import Money, Price, Quantity
204
+
205
+ spec = SUPPORTED_BINANCE_PERP_SPECS[raw_symbol]
206
+ base_currency = getattr(currencies, spec.base_currency)
207
+ return CryptoPerpetual(
208
+ instrument_id=InstrumentId(
209
+ symbol=Symbol(f"{raw_symbol}-PERP"),
210
+ venue=Venue("BINANCE"),
211
+ ),
212
+ raw_symbol=Symbol(raw_symbol),
213
+ base_currency=base_currency,
214
+ quote_currency=currencies.USDT,
215
+ settlement_currency=currencies.USDT,
216
+ is_inverse=False,
217
+ price_precision=spec.price_precision,
218
+ price_increment=Price.from_str(spec.price_increment),
219
+ size_precision=spec.size_precision,
220
+ size_increment=Quantity.from_str(spec.size_increment),
221
+ max_quantity=Quantity.from_str(spec.max_quantity),
222
+ min_quantity=Quantity.from_str(spec.min_quantity),
223
+ max_notional=None,
224
+ min_notional=Money(10.00, currencies.USDT),
225
+ max_price=Price.from_str(spec.max_price),
226
+ min_price=Price.from_str(spec.min_price),
227
+ margin_init=Decimal(spec.margin_init),
228
+ margin_maint=Decimal(spec.margin_maint),
229
+ maker_fee=Decimal(spec.maker_fee),
230
+ taker_fee=Decimal(spec.taker_fee),
231
+ ts_event=1646199312128000000,
232
+ ts_init=1646199342953849862,
233
+ )
234
+
235
+
236
+ def timeframe_to_nautilus(timeframe: str) -> str:
237
+ try:
238
+ return _TIMEFRAME_MAP[timeframe.lower()]
239
+ except KeyError as exc:
240
+ raise ValueError(f"Unsupported timeframe {timeframe!r}") from exc
241
+
242
+
243
+ def ensure_utc_ohlcv(data: pd.DataFrame) -> pd.DataFrame:
244
+ """
245
+ Return Nautilus-compatible OHLCV data.
246
+
247
+ Required output columns are lowercase: open, high, low, close, volume.
248
+ Index is a UTC DatetimeIndex.
249
+ """
250
+ df = data.copy()
251
+ rename = {
252
+ "Date": "timestamp",
253
+ "Datetime": "timestamp",
254
+ "Open": "open",
255
+ "High": "high",
256
+ "Low": "low",
257
+ "Close": "close",
258
+ "Volume": "volume",
259
+ }
260
+ df = df.rename(columns=rename)
261
+ if "timestamp" in df.columns:
262
+ df["timestamp"] = pd.to_datetime(df["timestamp"], utc=True)
263
+ df = df.set_index("timestamp")
264
+ if not isinstance(df.index, pd.DatetimeIndex):
265
+ raise ValueError("data must have a DatetimeIndex or timestamp column")
266
+ if df.index.tz is None:
267
+ df.index = df.index.tz_localize("UTC")
268
+ else:
269
+ df.index = df.index.tz_convert("UTC")
270
+
271
+ required = ["open", "high", "low", "close", "volume"]
272
+ missing = [c for c in required if c not in df.columns]
273
+ if missing:
274
+ raise ValueError(f"missing OHLCV columns: {missing}")
275
+ return df[required].sort_index()