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,197 @@
1
+ """
2
+ Execution contract taxonomy for QuantBT backtest engines.
3
+
4
+ The contract object is deliberately small and serializable. It describes what a
5
+ backend promises to simulate; hot kernels receive integer codes compiled from
6
+ these records in later phases.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from dataclasses import asdict, dataclass
12
+ from enum import Enum
13
+ from typing import Dict, Mapping
14
+
15
+
16
+ class SignalPhase(str, Enum):
17
+ BAR_OPEN = "bar_open"
18
+ BAR_CLOSE = "bar_close"
19
+
20
+
21
+ class FillPhase(str, Enum):
22
+ SAME_OPEN = "same_open"
23
+ SAME_CLOSE = "same_close"
24
+ NEXT_OPEN = "next_open"
25
+ NEXT_CLOSE = "next_close"
26
+
27
+
28
+ class MarketFillPolicy(str, Enum):
29
+ CLOSE = "close"
30
+ OPEN = "open"
31
+ NEXT_OPEN = "next_open"
32
+
33
+
34
+ class StopGapPolicy(str, Enum):
35
+ OPEN_WORSE_THAN_TRIGGER = "open_worse_than_trigger"
36
+
37
+
38
+ class TakeProfitGapPolicy(str, Enum):
39
+ LIMIT_PRICE_CONSERVATIVE = "limit_price_conservative"
40
+ OPEN_PRICE_IMPROVEMENT = "open_price_improvement"
41
+
42
+
43
+ class IntrabarSameBarPolicy(str, Enum):
44
+ CONSERVATIVE = "conservative"
45
+ STOP_FIRST = "stop_first"
46
+ TP_FIRST = "tp_first"
47
+ OHLC_PATH = "ohlc_path"
48
+ OLHC_PATH = "olhc_path"
49
+ REJECT_AMBIGUOUS = "reject_ambiguous"
50
+ LOWER_TIMEFRAME_REQUIRED = "lower_timeframe_required"
51
+
52
+
53
+ class TrailingUpdatePhase(str, Enum):
54
+ NONE = "none"
55
+ NEXT_BAR = "next_bar"
56
+
57
+
58
+ class FundingPhase(str, Enum):
59
+ POSITION_AT_EVENT = "position_at_event"
60
+ POSITION_AT_CLOSE = "position_at_close"
61
+
62
+
63
+ class LiquidationPriority(str, Enum):
64
+ LIQUIDATION_FIRST_AT_GAP = "liquidation_first_at_gap"
65
+ USER_STOP_FIRST = "user_stop_first"
66
+
67
+
68
+ class AmbiguityPolicy(str, Enum):
69
+ FLAG_AND_CONSERVATIVE = "flag_and_conservative"
70
+ REJECT = "reject"
71
+ LOWER_TIMEFRAME_REQUIRED = "lower_timeframe_required"
72
+
73
+
74
+ @dataclass(frozen=True)
75
+ class ExecutionContract:
76
+ engine_id: str
77
+ signal_phase: SignalPhase
78
+ entry_fill_phase: FillPhase
79
+ market_fill_policy: MarketFillPolicy
80
+ stop_gap_policy: StopGapPolicy = StopGapPolicy.OPEN_WORSE_THAN_TRIGGER
81
+ take_profit_gap_policy: TakeProfitGapPolicy = TakeProfitGapPolicy.LIMIT_PRICE_CONSERVATIVE
82
+ same_bar_policy: IntrabarSameBarPolicy = IntrabarSameBarPolicy.CONSERVATIVE
83
+ trailing_update_phase: TrailingUpdatePhase = TrailingUpdatePhase.NONE
84
+ funding_phase: FundingPhase = FundingPhase.POSITION_AT_EVENT
85
+ liquidation_priority: LiquidationPriority = LiquidationPriority.LIQUIDATION_FIRST_AT_GAP
86
+ close_on_last_bar: bool = True
87
+ ambiguity_policy: AmbiguityPolicy = AmbiguityPolicy.FLAG_AND_CONSERVATIVE
88
+ strict_data: bool = True
89
+
90
+ def __post_init__(self) -> None:
91
+ if not self.engine_id:
92
+ raise ValueError("engine_id is required")
93
+
94
+ @classmethod
95
+ def close_target(cls) -> "ExecutionContract":
96
+ return cls(
97
+ engine_id="close_target_v2",
98
+ signal_phase=SignalPhase.BAR_CLOSE,
99
+ entry_fill_phase=FillPhase.SAME_CLOSE,
100
+ market_fill_policy=MarketFillPolicy.CLOSE,
101
+ trailing_update_phase=TrailingUpdatePhase.NONE,
102
+ close_on_last_bar=False,
103
+ )
104
+
105
+ @classmethod
106
+ def next_open(cls) -> "ExecutionContract":
107
+ return cls(
108
+ engine_id="next_open_v1",
109
+ signal_phase=SignalPhase.BAR_CLOSE,
110
+ entry_fill_phase=FillPhase.NEXT_OPEN,
111
+ market_fill_policy=MarketFillPolicy.NEXT_OPEN,
112
+ trailing_update_phase=TrailingUpdatePhase.NONE,
113
+ )
114
+
115
+ @classmethod
116
+ def intrabar_bracket(
117
+ cls,
118
+ *,
119
+ same_bar_policy: IntrabarSameBarPolicy = IntrabarSameBarPolicy.CONSERVATIVE,
120
+ trailing_update_phase: TrailingUpdatePhase = TrailingUpdatePhase.NEXT_BAR,
121
+ take_profit_gap_policy: TakeProfitGapPolicy = TakeProfitGapPolicy.LIMIT_PRICE_CONSERVATIVE,
122
+ close_on_last_bar: bool = True,
123
+ ) -> "ExecutionContract":
124
+ return cls(
125
+ engine_id="intrabar_bracket_v1",
126
+ signal_phase=SignalPhase.BAR_CLOSE,
127
+ entry_fill_phase=FillPhase.NEXT_OPEN,
128
+ market_fill_policy=MarketFillPolicy.NEXT_OPEN,
129
+ same_bar_policy=same_bar_policy,
130
+ trailing_update_phase=trailing_update_phase,
131
+ take_profit_gap_policy=take_profit_gap_policy,
132
+ close_on_last_bar=close_on_last_bar,
133
+ )
134
+
135
+ @classmethod
136
+ def fill_replay(cls) -> "ExecutionContract":
137
+ return cls(
138
+ engine_id="fill_replay_v1",
139
+ signal_phase=SignalPhase.BAR_CLOSE,
140
+ entry_fill_phase=FillPhase.NEXT_OPEN,
141
+ market_fill_policy=MarketFillPolicy.NEXT_OPEN,
142
+ )
143
+
144
+ @classmethod
145
+ def event_lifecycle(cls) -> "ExecutionContract":
146
+ return cls(
147
+ engine_id="event_lifecycle_v2",
148
+ signal_phase=SignalPhase.BAR_CLOSE,
149
+ entry_fill_phase=FillPhase.NEXT_OPEN,
150
+ market_fill_policy=MarketFillPolicy.NEXT_OPEN,
151
+ )
152
+
153
+ def to_metadata(self) -> Dict:
154
+ payload = asdict(self)
155
+ for key, value in list(payload.items()):
156
+ if isinstance(value, Enum):
157
+ payload[key] = value.value
158
+ return payload
159
+
160
+ @classmethod
161
+ def from_metadata(cls, metadata: Mapping | "ExecutionContract") -> "ExecutionContract":
162
+ if isinstance(metadata, ExecutionContract):
163
+ return metadata
164
+ payload = dict(metadata or {})
165
+ if not payload:
166
+ raise ValueError("execution contract metadata is empty")
167
+ return cls(
168
+ engine_id=str(payload["engine_id"]),
169
+ signal_phase=SignalPhase(payload["signal_phase"]),
170
+ entry_fill_phase=FillPhase(payload["entry_fill_phase"]),
171
+ market_fill_policy=MarketFillPolicy(payload["market_fill_policy"]),
172
+ stop_gap_policy=StopGapPolicy(payload.get("stop_gap_policy", StopGapPolicy.OPEN_WORSE_THAN_TRIGGER.value)),
173
+ take_profit_gap_policy=TakeProfitGapPolicy(payload.get("take_profit_gap_policy", TakeProfitGapPolicy.LIMIT_PRICE_CONSERVATIVE.value)),
174
+ same_bar_policy=IntrabarSameBarPolicy(payload.get("same_bar_policy", IntrabarSameBarPolicy.CONSERVATIVE.value)),
175
+ trailing_update_phase=TrailingUpdatePhase(payload.get("trailing_update_phase", TrailingUpdatePhase.NONE.value)),
176
+ funding_phase=FundingPhase(payload.get("funding_phase", FundingPhase.POSITION_AT_EVENT.value)),
177
+ liquidation_priority=LiquidationPriority(payload.get("liquidation_priority", LiquidationPriority.LIQUIDATION_FIRST_AT_GAP.value)),
178
+ close_on_last_bar=bool(payload.get("close_on_last_bar", True)),
179
+ ambiguity_policy=AmbiguityPolicy(payload.get("ambiguity_policy", AmbiguityPolicy.FLAG_AND_CONSERVATIVE.value)),
180
+ strict_data=bool(payload.get("strict_data", True)),
181
+ )
182
+
183
+
184
+ EXECUTION_CONTRACT_REGISTRY: Dict[str, ExecutionContract] = {
185
+ "close_target_v2": ExecutionContract.close_target(),
186
+ "next_open_v1": ExecutionContract.next_open(),
187
+ "intrabar_bracket_v1": ExecutionContract.intrabar_bracket(),
188
+ "fill_replay_v1": ExecutionContract.fill_replay(),
189
+ "event_lifecycle_v2": ExecutionContract.event_lifecycle(),
190
+ }
191
+
192
+
193
+ def get_execution_contract(engine_id: str) -> ExecutionContract:
194
+ key = str(engine_id).lower().strip()
195
+ if key not in EXECUTION_CONTRACT_REGISTRY:
196
+ raise KeyError(f"unknown execution contract {engine_id!r}")
197
+ return EXECUTION_CONTRACT_REGISTRY[key]