des137 commited on
Commit
6413ecc
·
1 Parent(s): 5779fac

Deploy Quantum Finance Analyzer

Browse files
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ __pycache__/
2
+ *.pyc
README.md CHANGED
@@ -1,14 +1,58 @@
1
  ---
2
  title: Quantum Finance Analyzer
3
- emoji: 📊
4
  colorFrom: indigo
5
- colorTo: green
6
  sdk: gradio
7
- sdk_version: 6.2.0
8
  app_file: app.py
9
  pinned: false
10
  license: mit
11
- short_description: CrewAI for searching through quantum finance applications
12
  ---
13
 
14
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  title: Quantum Finance Analyzer
3
+ emoji: "⚗"
4
  colorFrom: indigo
5
+ colorTo: purple
6
  sdk: gradio
7
+ sdk_version: "4.44.0"
8
  app_file: app.py
9
  pinned: false
10
  license: mit
 
11
  ---
12
 
13
+ # Quantum Finance Feasibility Analyzer
14
+
15
+ An interactive tool for evaluating quantum computing applications in finance.
16
+ Assess whether your quantum finance ideas are viable on current NISQ hardware.
17
+
18
+ ## Features
19
+
20
+ - **Resource Estimation**: Calculate quantum resources for QAOA, Amplitude Estimation, and Grover's Search
21
+ - **Classical Benchmarks**: Compare quantum approaches against classical implementations (portfolio optimization, option pricing)
22
+ - **Use Case Analysis**: Pre-built feasibility analysis for common quantum finance applications
23
+ - **Custom Evaluation**: Evaluate your own quantum finance ideas with quick analysis or full CrewAI multi-agent evaluation
24
+
25
+ ## Supported Quantum Hardware
26
+
27
+ - IBM Osprey (433 qubits)
28
+ - IBM Condor (1121 qubits)
29
+ - IonQ Forte (36 qubits)
30
+ - Google Sycamore (72 qubits)
31
+
32
+ ## Use Cases
33
+
34
+ 1. **Portfolio Optimization (QAOA)** - Quantum optimization for asset allocation
35
+ 2. **Option Pricing (Amplitude Estimation)** - Quantum speedup for derivatives pricing
36
+ 3. **Fraud Detection (Quantum ML)** - Variational quantum classifiers for anomaly detection
37
+ 4. **Risk Analysis (Quantum Monte Carlo)** - VaR calculations with quantum acceleration
38
+ 5. **Credit Scoring (VQC)** - Quantum-enhanced credit risk models
39
+
40
+ ## Local Development
41
+
42
+ ```bash
43
+ pip install -r requirements.txt
44
+ python app.py
45
+ ```
46
+
47
+ ## CLI Usage
48
+
49
+ ```bash
50
+ python main.py --idea "Your quantum finance idea"
51
+ python main.py --batch # Run batch evaluation
52
+ ```
53
+
54
+ ## Built With
55
+
56
+ - [CrewAI](https://crewai.com) - Multi-agent AI framework
57
+ - [Gradio](https://gradio.app) - Web interface
58
+ - [Qiskit](https://qiskit.org) - Quantum computing framework
app.py ADDED
@@ -0,0 +1,837 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Gradio Demo App for Quantum Finance Feasibility Analysis Framework.
4
+
5
+ This app provides an interactive interface for:
6
+ - Quantum resource estimation (QAOA, Amplitude Estimation, Grover's)
7
+ - Classical benchmark comparisons (portfolio optimization, option pricing)
8
+ - Multi-agent evaluation of quantum finance ideas
9
+ - Pre-built use case demonstrations
10
+ """
11
+
12
+ import sys
13
+ from pathlib import Path
14
+
15
+ # Add src to path
16
+ sys.path.insert(0, str(Path(__file__).parent / "src"))
17
+
18
+ import gradio as gr
19
+ import numpy as np
20
+ import pandas as pd
21
+
22
+ from tools import (
23
+ QuantumResourceEstimator,
24
+ ClassicalPortfolioOptimizer,
25
+ OptionPricer,
26
+ FinanceDataCollector,
27
+ )
28
+
29
+
30
+ # ============================================================================
31
+ # QUANTUM RESOURCE ESTIMATION TAB
32
+ # ============================================================================
33
+
34
+ def estimate_qaoa_resources(hardware: str, num_assets: int, p_layers: int):
35
+ """Estimate QAOA resources for portfolio optimization."""
36
+ hardware_map = {
37
+ "IBM Osprey (433 qubits)": "ibm_osprey",
38
+ "IBM Condor (1121 qubits)": "ibm_condor",
39
+ "IonQ Forte (36 qubits)": "ionq_forte",
40
+ "Google Sycamore (72 qubits)": "google_sycamore",
41
+ }
42
+
43
+ estimator = QuantumResourceEstimator(hardware_map[hardware])
44
+ result = estimator.estimate_qaoa_resources(num_assets=int(num_assets), p_layers=int(p_layers))
45
+
46
+ # Format output
47
+ feasibility = "FEASIBLE" if result['feasible_on_hardware'] else "NOT FEASIBLE"
48
+ feasibility_color = "green" if result['feasible_on_hardware'] else "red"
49
+
50
+ output = f"""## QAOA Resource Estimation Results
51
+
52
+ ### Hardware: {hardware}
53
+
54
+ | Metric | Value |
55
+ |--------|-------|
56
+ | Qubits Required | {result['qubits_required']} |
57
+ | Qubits Available | {result['qubits_available']} |
58
+ | 1-Qubit Gates | {result['total_1q_gates']:,} |
59
+ | 2-Qubit Gates | {result['total_2q_gates']:,} |
60
+ | Circuit Depth | {result['circuit_depth']} |
61
+ | Execution Time | {result['execution_time_us']:.2f} us |
62
+ | Coherence Time | {result['coherence_time_us']:.0f} us |
63
+ | Success Probability | {result['success_probability']:.2e} |
64
+
65
+ ### Feasibility: **{feasibility}**
66
+
67
+ **Bottleneck:** {result['bottleneck']}
68
+ """
69
+ return output
70
+
71
+
72
+ def estimate_amplitude_resources(hardware: str, precision_bits: int, oracle_qubits: int):
73
+ """Estimate Amplitude Estimation resources for option pricing."""
74
+ hardware_map = {
75
+ "IBM Osprey (433 qubits)": "ibm_osprey",
76
+ "IBM Condor (1121 qubits)": "ibm_condor",
77
+ "IonQ Forte (36 qubits)": "ionq_forte",
78
+ "Google Sycamore (72 qubits)": "google_sycamore",
79
+ }
80
+
81
+ estimator = QuantumResourceEstimator(hardware_map[hardware])
82
+ result = estimator.estimate_amplitude_estimation_resources(
83
+ precision_bits=int(precision_bits),
84
+ num_qubits_oracle=int(oracle_qubits)
85
+ )
86
+
87
+ feasibility = "FEASIBLE" if result['feasible_on_hardware'] else "NOT FEASIBLE"
88
+
89
+ output = f"""## Amplitude Estimation Resource Results
90
+
91
+ ### Hardware: {hardware}
92
+
93
+ | Metric | Value |
94
+ |--------|-------|
95
+ | Qubits Required | {result['qubits_required']} |
96
+ | Qubits Available | {result['qubits_available']} |
97
+ | Oracle Calls | {result['oracle_calls']:,} |
98
+ | 2-Qubit Gates | {result['total_2q_gates']:,} |
99
+ | Execution Time | {result['execution_time_us']:.2f} us |
100
+ | Coherence Time | {result['coherence_time_us']:.0f} us |
101
+ | Success Probability | {result['success_probability']:.2e} |
102
+
103
+ ### Feasibility: **{feasibility}**
104
+
105
+ **Bottleneck:** {result['bottleneck']}
106
+
107
+ **Note:** Amplitude estimation provides quadratic speedup over classical Monte Carlo
108
+ for option pricing, but requires fault-tolerant quantum computers for practical precision.
109
+ """
110
+ return output
111
+
112
+
113
+ def estimate_grover_resources(hardware: str, search_space_log: int):
114
+ """Estimate Grover's search resources for fraud detection."""
115
+ hardware_map = {
116
+ "IBM Osprey (433 qubits)": "ibm_osprey",
117
+ "IBM Condor (1121 qubits)": "ibm_condor",
118
+ "IonQ Forte (36 qubits)": "ionq_forte",
119
+ "Google Sycamore (72 qubits)": "google_sycamore",
120
+ }
121
+
122
+ search_space_size = 10 ** int(search_space_log)
123
+ estimator = QuantumResourceEstimator(hardware_map[hardware])
124
+ result = estimator.estimate_grover_resources(search_space_size=search_space_size)
125
+
126
+ feasibility = "FEASIBLE" if result['feasible_on_hardware'] else "NOT FEASIBLE"
127
+
128
+ output = f"""## Grover's Search Resource Results
129
+
130
+ ### Hardware: {hardware}
131
+ ### Search Space: 10^{search_space_log} = {search_space_size:,} records
132
+
133
+ | Metric | Value |
134
+ |--------|-------|
135
+ | Qubits Required | {result['qubits_required']} |
136
+ | Qubits Available | {result['qubits_available']} |
137
+ | Grover Iterations | {result['grover_iterations']:,} |
138
+ | 2-Qubit Gates | {result['total_2q_gates']:,} |
139
+ | Execution Time | {result['execution_time_us']:.2f} us |
140
+ | Coherence Time | {result['coherence_time_us']:.0f} us |
141
+ | Success Probability | {result['success_probability']:.2e} |
142
+
143
+ ### Feasibility: **{feasibility}**
144
+
145
+ **Classical Speedup:** {result['classical_speedup']}
146
+
147
+ **Bottleneck:** {result['bottleneck']}
148
+ """
149
+ return output
150
+
151
+
152
+ # ============================================================================
153
+ # CLASSICAL BENCHMARKS TAB
154
+ # ============================================================================
155
+
156
+ def run_portfolio_optimization(n_assets: int, n_trials: int):
157
+ """Run classical portfolio optimization benchmark."""
158
+ collector = FinanceDataCollector(
159
+ tickers=FinanceDataCollector.DEFAULT_TICKERS[:int(n_assets)]
160
+ )
161
+
162
+ prices = collector.fetch_historical_data(period="1y")
163
+ returns = collector.calculate_returns(prices)
164
+ cov_matrix = collector.calculate_covariance_matrix(returns)
165
+ exp_returns = collector.calculate_expected_returns(returns)
166
+
167
+ optimizer = ClassicalPortfolioOptimizer(
168
+ exp_returns.values,
169
+ cov_matrix.values
170
+ )
171
+
172
+ result = optimizer.optimize_markowitz()
173
+ timing = optimizer.benchmark_timing(n_trials=int(n_trials))
174
+
175
+ # Format weights table
176
+ weights_df = pd.DataFrame({
177
+ 'Asset': exp_returns.index,
178
+ 'Weight': [f"{w:.4f}" for w in result['weights']],
179
+ 'Expected Return': [f"{r:.4f}" for r in exp_returns.values]
180
+ })
181
+
182
+ # Top allocations
183
+ top_indices = np.argsort(result['weights'])[-5:][::-1]
184
+ top_assets = [(exp_returns.index[i], result['weights'][i]) for i in top_indices]
185
+
186
+ output = f"""## Classical Portfolio Optimization Results
187
+
188
+ ### Portfolio Statistics
189
+
190
+ | Metric | Value |
191
+ |--------|-------|
192
+ | Number of Assets | {n_assets} |
193
+ | Expected Annual Return | {result['expected_return']:.4f} ({result['expected_return']*100:.2f}%) |
194
+ | Annual Volatility | {result['volatility']:.4f} ({result['volatility']*100:.2f}%) |
195
+ | Sharpe Ratio | {result['sharpe_ratio']:.4f} |
196
+ | Solver | {result['solver']} |
197
+
198
+ ### Top 5 Portfolio Allocations
199
+
200
+ | Asset | Weight |
201
+ |-------|--------|
202
+ """
203
+ for asset, weight in top_assets:
204
+ output += f"| {asset} | {weight:.4f} ({weight*100:.2f}%) |\n"
205
+
206
+ output += f"""
207
+ ### Timing Benchmark ({n_trials} trials)
208
+
209
+ | Metric | Value |
210
+ |--------|-------|
211
+ | Mean Time | {timing['mean_time_ms']:.3f} ms |
212
+ | Std Dev | {timing['std_time_ms']:.3f} ms |
213
+ | Min Time | {timing['min_time_ms']:.3f} ms |
214
+ | Max Time | {timing['max_time_ms']:.3f} ms |
215
+
216
+ **Quantum Comparison:** QAOA would require ~{n_assets} qubits with O(n^2) 2-qubit gates per layer.
217
+ Classical optimization at this scale is highly efficient and quantum advantage is unlikely.
218
+ """
219
+ return output
220
+
221
+
222
+ def run_option_pricing(spot: float, strike: float, maturity: float, rate: float, volatility: float, n_paths: int):
223
+ """Run option pricing comparison."""
224
+ # Black-Scholes analytical
225
+ bs_price = OptionPricer.black_scholes_call(
226
+ S=spot, K=strike, T=maturity, r=rate, sigma=volatility
227
+ )
228
+
229
+ # Monte Carlo
230
+ mc_result = OptionPricer.monte_carlo_call(
231
+ S=spot, K=strike, T=maturity, r=rate, sigma=volatility,
232
+ n_paths=int(n_paths)
233
+ )
234
+
235
+ # Timing benchmark
236
+ import time
237
+ times = []
238
+ for _ in range(10):
239
+ start = time.perf_counter()
240
+ OptionPricer.monte_carlo_call(
241
+ S=spot, K=strike, T=maturity, r=rate, sigma=volatility,
242
+ n_paths=int(n_paths)
243
+ )
244
+ times.append(time.perf_counter() - start)
245
+
246
+ mean_time = np.mean(times) * 1000
247
+
248
+ output = f"""## Option Pricing Comparison
249
+
250
+ ### Parameters
251
+
252
+ | Parameter | Value |
253
+ |-----------|-------|
254
+ | Spot Price (S) | ${spot:.2f} |
255
+ | Strike Price (K) | ${strike:.2f} |
256
+ | Time to Maturity | {maturity:.2f} years |
257
+ | Risk-Free Rate | {rate*100:.2f}% |
258
+ | Volatility | {volatility*100:.2f}% |
259
+
260
+ ### Results
261
+
262
+ | Method | Price | Notes |
263
+ |--------|-------|-------|
264
+ | Black-Scholes (Analytical) | ${bs_price:.4f} | Exact solution |
265
+ | Monte Carlo ({n_paths:,} paths) | ${mc_result['price']:.4f} | Std Error: {mc_result['std_error']:.6f} |
266
+
267
+ **95% Confidence Interval:** ${mc_result['confidence_interval_95'][0]:.4f} - ${mc_result['confidence_interval_95'][1]:.4f}
268
+
269
+ ### Monte Carlo Timing (10 trials)
270
+
271
+ | Metric | Value |
272
+ |--------|-------|
273
+ | Mean Time | {mean_time:.3f} ms |
274
+ | Paths/Second | {int(n_paths)/(mean_time/1000):,.0f} |
275
+
276
+ ### Quantum Advantage Analysis
277
+
278
+ **Amplitude Estimation** promises quadratic speedup over Monte Carlo:
279
+ - Classical: O(1/epsilon^2) paths for precision epsilon
280
+ - Quantum: O(1/epsilon) oracle calls
281
+
282
+ For {volatility*100:.0f}% vol option with 0.01% precision:
283
+ - Classical Monte Carlo: ~100M paths needed
284
+ - Quantum (theoretical): ~10K oracle calls
285
+
286
+ **Reality Check:** Current NISQ hardware cannot achieve the required circuit depth
287
+ for meaningful amplitude estimation. Error rates and coherence times are limiting factors.
288
+ """
289
+ return output
290
+
291
+
292
+ # ============================================================================
293
+ # USE CASES TAB
294
+ # ============================================================================
295
+
296
+ TEST_CASES = [
297
+ {
298
+ 'id': 'portfolio_optimization',
299
+ 'name': 'Portfolio Optimization (QAOA)',
300
+ 'idea': 'Quantum portfolio optimization using QAOA for a 100-asset portfolio with mean-variance objective',
301
+ 'category': 'optimization',
302
+ 'description': 'Use QAOA to find optimal portfolio weights minimizing variance for target return.'
303
+ },
304
+ {
305
+ 'id': 'option_pricing',
306
+ 'name': 'Option Pricing (Amplitude Estimation)',
307
+ 'idea': 'Quantum amplitude estimation for pricing European call options with 8-bit precision',
308
+ 'category': 'pricing',
309
+ 'description': 'Use quantum amplitude estimation to price derivatives faster than Monte Carlo.'
310
+ },
311
+ {
312
+ 'id': 'fraud_detection',
313
+ 'name': 'Fraud Detection (Quantum ML)',
314
+ 'idea': 'Quantum machine learning classifier for real-time credit card fraud detection',
315
+ 'category': 'ml',
316
+ 'description': 'Use variational quantum classifiers for pattern recognition in transactions.'
317
+ },
318
+ {
319
+ 'id': 'risk_analysis',
320
+ 'name': 'Risk Analysis (Quantum Monte Carlo)',
321
+ 'idea': 'Quantum Monte Carlo for Value-at-Risk (VaR) calculation on a derivatives portfolio',
322
+ 'category': 'risk',
323
+ 'description': 'Use quantum speedup for risk metric calculations.'
324
+ },
325
+ {
326
+ 'id': 'credit_scoring',
327
+ 'name': 'Credit Scoring (VQC)',
328
+ 'idea': 'Variational quantum classifier for credit scoring using customer financial data',
329
+ 'category': 'ml',
330
+ 'description': 'Use VQC for binary classification of creditworthiness.'
331
+ }
332
+ ]
333
+
334
+
335
+ def analyze_use_case(case_name: str):
336
+ """Analyze a pre-built use case."""
337
+ case = next((c for c in TEST_CASES if c['name'] == case_name), None)
338
+ if not case:
339
+ return "Use case not found"
340
+
341
+ # Run resource estimation based on category
342
+ estimator = QuantumResourceEstimator('ibm_osprey')
343
+
344
+ if case['category'] == 'optimization':
345
+ resources = estimator.estimate_qaoa_resources(num_assets=100, p_layers=3)
346
+ algorithm = "QAOA"
347
+ classical_time = "~10ms with scipy"
348
+ elif case['category'] == 'pricing':
349
+ resources = estimator.estimate_amplitude_estimation_resources(
350
+ precision_bits=8, num_qubits_oracle=20
351
+ )
352
+ algorithm = "Amplitude Estimation"
353
+ classical_time = "~100ms Monte Carlo (1M paths)"
354
+ elif case['category'] == 'risk':
355
+ resources = estimator.estimate_amplitude_estimation_resources(
356
+ precision_bits=10, num_qubits_oracle=30
357
+ )
358
+ algorithm = "Quantum Monte Carlo"
359
+ classical_time = "~1s Monte Carlo (10M paths)"
360
+ else: # ml
361
+ resources = estimator.estimate_qaoa_resources(num_assets=50, p_layers=5)
362
+ algorithm = "Variational Quantum Classifier"
363
+ classical_time = "~5ms classical ML inference"
364
+
365
+ feasibility = "FEASIBLE" if resources['feasible_on_hardware'] else "NOT FEASIBLE"
366
+
367
+ output = f"""## Use Case Analysis: {case['name']}
368
+
369
+ ### Description
370
+ {case['description']}
371
+
372
+ ### Proposed Idea
373
+ > {case['idea']}
374
+
375
+ ### Algorithm: {algorithm}
376
+
377
+ ### Resource Requirements (IBM Osprey)
378
+
379
+ | Metric | Value |
380
+ |--------|-------|
381
+ | Qubits Required | {resources['qubits_required']} |
382
+ | Qubits Available | {resources['qubits_available']} |
383
+ | Total 2-Qubit Gates | {resources.get('total_2q_gates', 'N/A'):,} |
384
+ | Execution Time | {resources['execution_time_us']:.2f} us |
385
+ | Coherence Time | {resources['coherence_time_us']:.0f} us |
386
+ | Success Probability | {resources['success_probability']:.2e} |
387
+
388
+ ### Feasibility Assessment: **{feasibility}**
389
+
390
+ **Bottleneck:** {resources['bottleneck']}
391
+
392
+ ### Quantum vs Classical Comparison
393
+
394
+ | Aspect | Quantum | Classical |
395
+ |--------|---------|-----------|
396
+ | Execution Time | {resources['execution_time_us']:.2f} us (per shot) | {classical_time} |
397
+ | Error Rate | {(1-resources['success_probability'])*100:.2f}% failure | Deterministic |
398
+ | Scalability | Limited by coherence | Memory-bound |
399
+
400
+ ### Verdict
401
+
402
+ """
403
+ if resources['feasible_on_hardware']:
404
+ output += """**Potentially viable** on current hardware, but likely no practical advantage over
405
+ classical methods due to:
406
+ - High shot count requirements for statistical accuracy
407
+ - Variational parameter optimization overhead
408
+ - Limited problem sizes that fit in coherence window
409
+ """
410
+ else:
411
+ output += f"""**Not viable** on current NISQ hardware due to:
412
+ - {resources['bottleneck']}
413
+
414
+ **Timeline:** This application likely requires fault-tolerant quantum computers
415
+ (estimated 2030+ for practical advantage).
416
+ """
417
+
418
+ return output
419
+
420
+
421
+ # ============================================================================
422
+ # IDEA EVALUATION TAB (CrewAI Integration)
423
+ # ============================================================================
424
+
425
+ def evaluate_idea_quick(idea: str):
426
+ """Quick evaluation without full CrewAI (for demo purposes)."""
427
+ if not idea.strip():
428
+ return "Please enter a quantum finance idea to evaluate."
429
+
430
+ # Analyze the idea based on keywords
431
+ idea_lower = idea.lower()
432
+
433
+ # Determine algorithm type
434
+ if any(word in idea_lower for word in ['portfolio', 'optimization', 'qaoa']):
435
+ algorithm = "QAOA"
436
+ estimator = QuantumResourceEstimator('ibm_osprey')
437
+ # Extract asset count if mentioned
438
+ import re
439
+ match = re.search(r'(\d+)[- ]?asset', idea_lower)
440
+ n_assets = int(match.group(1)) if match else 50
441
+ resources = estimator.estimate_qaoa_resources(num_assets=n_assets, p_layers=3)
442
+
443
+ elif any(word in idea_lower for word in ['option', 'pricing', 'amplitude', 'derivative']):
444
+ algorithm = "Amplitude Estimation"
445
+ estimator = QuantumResourceEstimator('ibm_osprey')
446
+ resources = estimator.estimate_amplitude_estimation_resources(
447
+ precision_bits=8, num_qubits_oracle=20
448
+ )
449
+
450
+ elif any(word in idea_lower for word in ['fraud', 'detection', 'search', 'grover']):
451
+ algorithm = "Grover's Search / Quantum ML"
452
+ estimator = QuantumResourceEstimator('ibm_osprey')
453
+ resources = estimator.estimate_grover_resources(search_space_size=1_000_000)
454
+
455
+ elif any(word in idea_lower for word in ['risk', 'var', 'monte carlo', 'simulation']):
456
+ algorithm = "Quantum Monte Carlo"
457
+ estimator = QuantumResourceEstimator('ibm_osprey')
458
+ resources = estimator.estimate_amplitude_estimation_resources(
459
+ precision_bits=10, num_qubits_oracle=25
460
+ )
461
+
462
+ elif any(word in idea_lower for word in ['credit', 'scoring', 'classifier', 'ml', 'machine learning']):
463
+ algorithm = "Variational Quantum Classifier"
464
+ estimator = QuantumResourceEstimator('ibm_osprey')
465
+ resources = estimator.estimate_qaoa_resources(num_assets=30, p_layers=5)
466
+
467
+ else:
468
+ algorithm = "General Variational Algorithm"
469
+ estimator = QuantumResourceEstimator('ibm_osprey')
470
+ resources = estimator.estimate_qaoa_resources(num_assets=20, p_layers=2)
471
+
472
+ feasibility = "FEASIBLE" if resources['feasible_on_hardware'] else "NOT FEASIBLE"
473
+
474
+ # Generate assessment scores
475
+ scores = {
476
+ 'algorithm_fit': 0.7 if resources['feasible_on_hardware'] else 0.3,
477
+ 'hardware_readiness': resources['success_probability'],
478
+ 'classical_comparison': 0.2 if not resources['feasible_on_hardware'] else 0.5,
479
+ 'business_viability': 0.4 if resources['feasible_on_hardware'] else 0.1,
480
+ }
481
+
482
+ output = f"""## Quick Feasibility Analysis
483
+
484
+ ### Your Idea
485
+ > {idea}
486
+
487
+ ### Identified Algorithm: {algorithm}
488
+
489
+ ### Hardware Feasibility (IBM Osprey)
490
+
491
+ | Metric | Value |
492
+ |--------|-------|
493
+ | Qubits Required | {resources['qubits_required']} |
494
+ | Qubits Available | {resources['qubits_available']} |
495
+ | Execution Time | {resources['execution_time_us']:.2f} us |
496
+ | Coherence Time | {resources['coherence_time_us']:.0f} us |
497
+ | Success Probability | {resources['success_probability']:.2e} |
498
+
499
+ ### Overall Feasibility: **{feasibility}**
500
+
501
+ **Primary Bottleneck:** {resources['bottleneck']}
502
+
503
+ ### Assessment Scores (0-1 scale)
504
+
505
+ | Dimension | Score | Interpretation |
506
+ |-----------|-------|----------------|
507
+ | Algorithm Fit | {scores['algorithm_fit']:.2f} | {"Good match" if scores['algorithm_fit'] > 0.5 else "Poor match"} |
508
+ | Hardware Readiness | {scores['hardware_readiness']:.2e} | {"Ready" if scores['hardware_readiness'] > 0.01 else "Not ready"} |
509
+ | Classical Advantage | {scores['classical_comparison']:.2f} | {"Potential" if scores['classical_comparison'] > 0.4 else "Unlikely"} |
510
+ | Business Viability | {scores['business_viability']:.2f} | {"Viable" if scores['business_viability'] > 0.3 else "Premature"} |
511
+
512
+ ### Recommendations
513
+
514
+ """
515
+
516
+ if resources['feasible_on_hardware']:
517
+ output += """1. **Proof-of-concept possible** - The idea can be demonstrated on current hardware
518
+ 2. **Focus on small instances** - Limit problem size to stay within coherence window
519
+ 3. **Benchmark carefully** - Compare against optimized classical implementations
520
+ 4. **Hybrid approach** - Consider quantum-classical hybrid strategies
521
+ """
522
+ else:
523
+ output += """1. **Scale down** - Reduce problem size to fit hardware constraints
524
+ 2. **Wait for hardware** - Better quantum computers expected in 2-5 years
525
+ 3. **Classical alternatives** - Current classical methods likely more practical
526
+ 4. **Research angle** - Frame as algorithmic research rather than near-term application
527
+ """
528
+
529
+ output += """
530
+ ---
531
+ *Note: This is a quick analysis. For comprehensive multi-agent evaluation,
532
+ use the full CrewAI framework via CLI: `python main.py --idea "your idea"`*
533
+ """
534
+
535
+ return output
536
+
537
+
538
+ def run_full_evaluation(idea: str):
539
+ """Run full CrewAI evaluation (may take several minutes)."""
540
+ if not idea.strip():
541
+ return "Please enter a quantum finance idea to evaluate."
542
+
543
+ try:
544
+ from quantum_finance_crew import QuantumFinanceCrew
545
+
546
+ crew = QuantumFinanceCrew()
547
+ result = crew.evaluate(idea, verbose=False)
548
+
549
+ output = f"""## Full Multi-Agent Evaluation
550
+
551
+ ### Your Idea
552
+ > {idea}
553
+
554
+ ### CrewAI Analysis Complete
555
+
556
+ **Tasks Completed:** {result.get('tasks_completed', 'N/A')}
557
+
558
+ ### Final Assessment
559
+
560
+ {result.get('result', 'No result available')}
561
+
562
+ ---
563
+ *Evaluated by: Quantum Algorithm Expert, Error Correction Expert,
564
+ Classical Computing Expert, and Finance Domain Expert*
565
+ """
566
+ return output
567
+
568
+ except Exception as e:
569
+ return f"""## Evaluation Error
570
+
571
+ Could not run full CrewAI evaluation: {str(e)}
572
+
573
+ **Possible causes:**
574
+ - Missing API keys (OPENAI_API_KEY or ANTHROPIC_API_KEY)
575
+ - CrewAI configuration issues
576
+
577
+ **Alternative:** Use the Quick Analysis above for instant resource estimation.
578
+ """
579
+
580
+
581
+ # ============================================================================
582
+ # BUILD GRADIO APP
583
+ # ============================================================================
584
+
585
+ def create_app():
586
+ """Create the Gradio application."""
587
+
588
+ with gr.Blocks(
589
+ title="Quantum Finance Feasibility Analyzer",
590
+ theme=gr.themes.Soft()
591
+ ) as app:
592
+
593
+ gr.Markdown("""
594
+ # Quantum Finance Feasibility Analyzer
595
+
596
+ An interactive tool for evaluating quantum computing applications in finance.
597
+ Assess whether your quantum finance ideas are viable on current NISQ hardware.
598
+
599
+ **Features:**
600
+ - Quantum resource estimation for QAOA, Amplitude Estimation, and Grover's Search
601
+ - Classical benchmark comparisons (portfolio optimization, option pricing)
602
+ - Pre-built use case analysis
603
+ - Custom idea evaluation
604
+ """)
605
+
606
+ with gr.Tabs():
607
+ # Tab 1: Resource Estimation
608
+ with gr.TabItem("Resource Estimation"):
609
+ gr.Markdown("## Quantum Resource Calculator")
610
+ gr.Markdown("Estimate the quantum resources required for different finance algorithms.")
611
+
612
+ with gr.Tabs():
613
+ # QAOA
614
+ with gr.TabItem("QAOA (Portfolio Optimization)"):
615
+ with gr.Row():
616
+ with gr.Column():
617
+ qaoa_hardware = gr.Dropdown(
618
+ choices=[
619
+ "IBM Osprey (433 qubits)",
620
+ "IBM Condor (1121 qubits)",
621
+ "IonQ Forte (36 qubits)",
622
+ "Google Sycamore (72 qubits)"
623
+ ],
624
+ value="IBM Osprey (433 qubits)",
625
+ label="Target Hardware"
626
+ )
627
+ qaoa_assets = gr.Slider(
628
+ minimum=5, maximum=200, value=50, step=5,
629
+ label="Number of Assets"
630
+ )
631
+ qaoa_layers = gr.Slider(
632
+ minimum=1, maximum=10, value=3, step=1,
633
+ label="QAOA Layers (p)"
634
+ )
635
+ qaoa_btn = gr.Button("Estimate Resources", variant="primary")
636
+ with gr.Column():
637
+ qaoa_output = gr.Markdown()
638
+
639
+ qaoa_btn.click(
640
+ estimate_qaoa_resources,
641
+ inputs=[qaoa_hardware, qaoa_assets, qaoa_layers],
642
+ outputs=qaoa_output
643
+ )
644
+
645
+ # Amplitude Estimation
646
+ with gr.TabItem("Amplitude Estimation (Option Pricing)"):
647
+ with gr.Row():
648
+ with gr.Column():
649
+ ae_hardware = gr.Dropdown(
650
+ choices=[
651
+ "IBM Osprey (433 qubits)",
652
+ "IBM Condor (1121 qubits)",
653
+ "IonQ Forte (36 qubits)",
654
+ "Google Sycamore (72 qubits)"
655
+ ],
656
+ value="IBM Osprey (433 qubits)",
657
+ label="Target Hardware"
658
+ )
659
+ ae_precision = gr.Slider(
660
+ minimum=2, maximum=12, value=8, step=1,
661
+ label="Precision Bits"
662
+ )
663
+ ae_oracle = gr.Slider(
664
+ minimum=5, maximum=50, value=20, step=5,
665
+ label="Oracle Qubits"
666
+ )
667
+ ae_btn = gr.Button("Estimate Resources", variant="primary")
668
+ with gr.Column():
669
+ ae_output = gr.Markdown()
670
+
671
+ ae_btn.click(
672
+ estimate_amplitude_resources,
673
+ inputs=[ae_hardware, ae_precision, ae_oracle],
674
+ outputs=ae_output
675
+ )
676
+
677
+ # Grover's Search
678
+ with gr.TabItem("Grover's Search (Fraud Detection)"):
679
+ with gr.Row():
680
+ with gr.Column():
681
+ grover_hardware = gr.Dropdown(
682
+ choices=[
683
+ "IBM Osprey (433 qubits)",
684
+ "IBM Condor (1121 qubits)",
685
+ "IonQ Forte (36 qubits)",
686
+ "Google Sycamore (72 qubits)"
687
+ ],
688
+ value="IBM Osprey (433 qubits)",
689
+ label="Target Hardware"
690
+ )
691
+ grover_space = gr.Slider(
692
+ minimum=3, maximum=9, value=6, step=1,
693
+ label="Search Space Size (10^x records)"
694
+ )
695
+ grover_btn = gr.Button("Estimate Resources", variant="primary")
696
+ with gr.Column():
697
+ grover_output = gr.Markdown()
698
+
699
+ grover_btn.click(
700
+ estimate_grover_resources,
701
+ inputs=[grover_hardware, grover_space],
702
+ outputs=grover_output
703
+ )
704
+
705
+ # Tab 2: Classical Benchmarks
706
+ with gr.TabItem("Classical Benchmarks"):
707
+ gr.Markdown("## Classical Finance Benchmarks")
708
+ gr.Markdown("Compare quantum approaches against classical implementations.")
709
+
710
+ with gr.Tabs():
711
+ with gr.TabItem("Portfolio Optimization"):
712
+ with gr.Row():
713
+ with gr.Column():
714
+ port_assets = gr.Slider(
715
+ minimum=5, maximum=25, value=15, step=1,
716
+ label="Number of Assets"
717
+ )
718
+ port_trials = gr.Slider(
719
+ minimum=10, maximum=500, value=100, step=10,
720
+ label="Timing Trials"
721
+ )
722
+ port_btn = gr.Button("Run Optimization", variant="primary")
723
+ with gr.Column():
724
+ port_output = gr.Markdown()
725
+
726
+ port_btn.click(
727
+ run_portfolio_optimization,
728
+ inputs=[port_assets, port_trials],
729
+ outputs=port_output
730
+ )
731
+
732
+ with gr.TabItem("Option Pricing"):
733
+ with gr.Row():
734
+ with gr.Column():
735
+ opt_spot = gr.Number(value=100, label="Spot Price ($)")
736
+ opt_strike = gr.Number(value=100, label="Strike Price ($)")
737
+ opt_maturity = gr.Slider(
738
+ minimum=0.1, maximum=2.0, value=1.0, step=0.1,
739
+ label="Time to Maturity (years)"
740
+ )
741
+ opt_rate = gr.Slider(
742
+ minimum=0.01, maximum=0.10, value=0.05, step=0.01,
743
+ label="Risk-Free Rate"
744
+ )
745
+ opt_vol = gr.Slider(
746
+ minimum=0.1, maximum=0.5, value=0.2, step=0.05,
747
+ label="Volatility"
748
+ )
749
+ opt_paths = gr.Slider(
750
+ minimum=10000, maximum=1000000, value=100000, step=10000,
751
+ label="Monte Carlo Paths"
752
+ )
753
+ opt_btn = gr.Button("Price Option", variant="primary")
754
+ with gr.Column():
755
+ opt_output = gr.Markdown()
756
+
757
+ opt_btn.click(
758
+ run_option_pricing,
759
+ inputs=[opt_spot, opt_strike, opt_maturity, opt_rate, opt_vol, opt_paths],
760
+ outputs=opt_output
761
+ )
762
+
763
+ # Tab 3: Use Cases
764
+ with gr.TabItem("Use Cases"):
765
+ gr.Markdown("## Pre-Built Use Case Analysis")
766
+ gr.Markdown("Explore detailed feasibility analysis for common quantum finance applications.")
767
+
768
+ with gr.Row():
769
+ with gr.Column():
770
+ use_case = gr.Dropdown(
771
+ choices=[c['name'] for c in TEST_CASES],
772
+ value=TEST_CASES[0]['name'],
773
+ label="Select Use Case"
774
+ )
775
+ use_case_btn = gr.Button("Analyze Use Case", variant="primary")
776
+ with gr.Column():
777
+ use_case_output = gr.Markdown()
778
+
779
+ use_case_btn.click(
780
+ analyze_use_case,
781
+ inputs=[use_case],
782
+ outputs=use_case_output
783
+ )
784
+
785
+ # Tab 4: Idea Evaluation
786
+ with gr.TabItem("Evaluate Your Idea"):
787
+ gr.Markdown("## Custom Idea Evaluation")
788
+ gr.Markdown("Enter your quantum finance idea for feasibility analysis.")
789
+
790
+ with gr.Row():
791
+ with gr.Column():
792
+ idea_input = gr.Textbox(
793
+ lines=4,
794
+ placeholder="Example: Quantum optimization for rebalancing a 50-asset ETF portfolio using QAOA with real-time market data...",
795
+ label="Your Quantum Finance Idea"
796
+ )
797
+ with gr.Row():
798
+ quick_btn = gr.Button("Quick Analysis", variant="primary")
799
+ full_btn = gr.Button("Full CrewAI Evaluation", variant="secondary")
800
+
801
+ gr.Markdown("""
802
+ **Quick Analysis:** Instant resource estimation and feasibility check.
803
+
804
+ **Full CrewAI Evaluation:** Comprehensive multi-agent analysis (requires API keys, may take several minutes).
805
+ """)
806
+
807
+ with gr.Column():
808
+ idea_output = gr.Markdown()
809
+
810
+ quick_btn.click(
811
+ evaluate_idea_quick,
812
+ inputs=[idea_input],
813
+ outputs=idea_output
814
+ )
815
+
816
+ full_btn.click(
817
+ run_full_evaluation,
818
+ inputs=[idea_input],
819
+ outputs=idea_output
820
+ )
821
+
822
+ gr.Markdown("""
823
+ ---
824
+ **Quantum Finance Feasibility Analysis Framework**
825
+
826
+ Built with CrewAI for multi-agent evaluation. Resource estimates based on current NISQ hardware specifications.
827
+
828
+ *For command-line usage:* `python main.py --help`
829
+ """)
830
+
831
+ return app
832
+
833
+
834
+ # Main entry point
835
+ if __name__ == "__main__":
836
+ app = create_app()
837
+ app.launch()
config/agents.yaml ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ quantum_algorithm_expert:
2
+ role: "Quantum Algorithm Expert"
3
+ goal: "Assess whether proposed finance applications map to known quantum algorithms (QAOA, VQE, Grover's, Amplitude Estimation) and estimate their computational complexity on NISQ hardware"
4
+ backstory: |
5
+ You are a leading expert in quantum algorithms with deep knowledge of variational quantum
6
+ eigensolver (VQE), Quantum Approximate Optimization Algorithm (QAOA), Grover's search,
7
+ and quantum amplitude estimation. You understand the theoretical speedups these algorithms
8
+ offer and their practical limitations on near-term intermediate-scale quantum (NISQ) devices.
9
+ You critically evaluate claims of quantum advantage and can identify when classical
10
+ algorithms remain competitive.
11
+ verbose: true
12
+ allow_delegation: true
13
+
14
+ quantum_error_correction_expert:
15
+ role: "Quantum Error Correction Expert"
16
+ goal: "Evaluate the impact of noise, decoherence, and error rates on proposed quantum finance applications using NISQ hardware constraints"
17
+ backstory: |
18
+ You specialize in quantum error correction and noise modeling for NISQ devices. You understand
19
+ current hardware limitations including qubit counts (<1,000 qubits), gate fidelities (99-99.9%),
20
+ coherence times, and connectivity constraints. You can estimate circuit depth limits and
21
+ determine whether proposed applications are feasible given realistic error budgets.
22
+ You are familiar with error mitigation techniques and can assess their effectiveness.
23
+ verbose: true
24
+ allow_delegation: true
25
+
26
+ classical_computing_expert:
27
+ role: "Classical Computing Expert"
28
+ goal: "Provide rigorous classical baselines and benchmarks to compare against proposed quantum solutions, identifying when classical methods are sufficient"
29
+ backstory: |
30
+ You are an expert in classical optimization, machine learning, and high-performance computing.
31
+ You know the state-of-the-art in classical solvers (Gurobi, CPLEX), GPU-accelerated computing,
32
+ tensor network methods, and Monte Carlo simulations. You can estimate classical runtime
33
+ complexity and identify when quantum approaches offer no practical advantage over
34
+ well-optimized classical implementations.
35
+ verbose: true
36
+ allow_delegation: true
37
+
38
+ finance_domain_expert:
39
+ role: "Finance Domain Expert"
40
+ goal: "Evaluate the commercial viability, regulatory fit, and practical constraints of quantum finance applications from an industry perspective"
41
+ backstory: |
42
+ You are a senior quantitative finance professional with expertise in portfolio optimization,
43
+ derivatives pricing, risk management, and fraud detection. You understand regulatory
44
+ requirements (Basel III/IV, SEC rules), latency constraints in trading, and the practical
45
+ challenges of deploying new technologies in financial institutions. You can assess whether
46
+ proposed quantum solutions address real business needs and fit within existing infrastructure.
47
+ verbose: true
48
+ allow_delegation: true
config/tasks.yaml ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ analyze_quantum_feasibility:
2
+ description: |
3
+ Analyze the quantum algorithm feasibility for the proposed finance application: {idea}
4
+
5
+ Evaluate:
6
+ 1. Which quantum algorithms (QAOA, VQE, Grover's, Amplitude Estimation, etc.) could apply
7
+ 2. Theoretical complexity improvements over classical approaches
8
+ 3. Required qubit count and circuit depth estimates
9
+ 4. Known limitations and open problems for this algorithm class
10
+
11
+ Provide a feasibility score (0-1) with detailed justification.
12
+ expected_output: |
13
+ A structured analysis containing:
14
+ - Applicable quantum algorithms with rationale
15
+ - Complexity analysis (quantum vs classical)
16
+ - Resource requirements (qubits, gates, depth)
17
+ - Feasibility score with justification
18
+ - Key bottlenecks and risks
19
+ agent: quantum_algorithm_expert
20
+
21
+ assess_nisq_constraints:
22
+ description: |
23
+ Assess the NISQ hardware constraints for implementing: {idea}
24
+
25
+ Consider:
26
+ 1. Current hardware capabilities (IBM, IonQ, Google - 2024-2026 roadmaps)
27
+ 2. Noise impact on algorithm performance
28
+ 3. Error mitigation strategies and their overhead
29
+ 4. Realistic timeline for hardware sufficient to run this application
30
+
31
+ Provide a hardware readiness score (0-1).
32
+ expected_output: |
33
+ A structured assessment containing:
34
+ - Hardware requirements vs current capabilities
35
+ - Noise sensitivity analysis
36
+ - Recommended error mitigation approaches
37
+ - Hardware readiness score with timeline estimate
38
+ - Critical hardware milestones needed
39
+ agent: quantum_error_correction_expert
40
+
41
+ benchmark_classical_alternatives:
42
+ description: |
43
+ Benchmark classical alternatives for: {idea}
44
+
45
+ Analyze:
46
+ 1. Best classical algorithms and solvers for this problem
47
+ 2. State-of-the-art performance on relevant benchmarks
48
+ 3. GPU/TPU acceleration potential
49
+ 4. Quantum-inspired classical methods (tensor networks, etc.)
50
+
51
+ Provide a classical competitiveness score (0-1, where 1 = classical is fully sufficient).
52
+ expected_output: |
53
+ A structured benchmark containing:
54
+ - Best classical approaches with performance data
55
+ - Scalability analysis
56
+ - Hardware costs (classical vs quantum)
57
+ - Classical competitiveness score
58
+ - Crossover point estimate (if any)
59
+ agent: classical_computing_expert
60
+
61
+ evaluate_business_viability:
62
+ description: |
63
+ Evaluate the business viability of: {idea}
64
+
65
+ Consider:
66
+ 1. Real business value and use case fit
67
+ 2. Regulatory and compliance implications
68
+ 3. Integration with existing financial infrastructure
69
+ 4. Cost-benefit analysis (quantum vs classical deployment)
70
+ 5. Risk tolerance of financial institutions for new technology
71
+
72
+ Provide a commercial viability score (0-1).
73
+ expected_output: |
74
+ A structured evaluation containing:
75
+ - Business value assessment
76
+ - Regulatory considerations
77
+ - Integration challenges
78
+ - Cost-benefit analysis
79
+ - Commercial viability score with timeline
80
+ - Recommended next steps
81
+ agent: finance_domain_expert
82
+
83
+ synthesize_final_assessment:
84
+ description: |
85
+ Synthesize all expert analyses into a final feasibility assessment for: {idea}
86
+
87
+ Integrate findings from:
88
+ - Quantum algorithm feasibility analysis
89
+ - NISQ hardware constraints assessment
90
+ - Classical benchmarking results
91
+ - Business viability evaluation
92
+
93
+ Determine overall quantum advantage potential and provide actionable recommendations.
94
+ expected_output: |
95
+ A comprehensive final report containing:
96
+ - Executive summary (2-3 sentences)
97
+ - Overall feasibility score (0-1) with breakdown
98
+ - Quantum advantage assessment (Yes/No/Hybrid with justification)
99
+ - Key bottlenecks ranked by severity
100
+ - Recommended alternatives if quantum not viable
101
+ - Actionable next steps
102
+ - Timeline estimate for viable implementation
103
+ agent: quantum_algorithm_expert
104
+ context:
105
+ - analyze_quantum_feasibility
106
+ - assess_nisq_constraints
107
+ - benchmark_classical_alternatives
108
+ - evaluate_business_viability
main.py ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Main entry point for the Quantum Finance Feasibility Analysis Framework.
4
+
5
+ Usage:
6
+ python main.py # Run demo evaluation
7
+ python main.py --idea "Your idea here" # Evaluate specific idea
8
+ python main.py --batch # Run batch evaluation on test cases
9
+ """
10
+
11
+ import argparse
12
+ import sys
13
+ from pathlib import Path
14
+
15
+ # Add src to path
16
+ sys.path.insert(0, str(Path(__file__).parent / "src"))
17
+
18
+ from quantum_finance_crew import QuantumFinanceCrew
19
+ from tools import (
20
+ QuantumResourceEstimator,
21
+ collect_experiment_data,
22
+ ClassicalPortfolioOptimizer
23
+ )
24
+ from utils import MetricsCollector, EvaluationMetrics
25
+
26
+
27
+ # Standard test cases for experiments
28
+ TEST_CASES = [
29
+ {
30
+ 'id': 'portfolio_optimization',
31
+ 'idea': 'Quantum portfolio optimization using QAOA for a 100-asset portfolio with mean-variance objective',
32
+ 'category': 'optimization'
33
+ },
34
+ {
35
+ 'id': 'option_pricing',
36
+ 'idea': 'Quantum amplitude estimation for pricing European call options with 8-bit precision',
37
+ 'category': 'pricing'
38
+ },
39
+ {
40
+ 'id': 'fraud_detection',
41
+ 'idea': 'Quantum machine learning classifier for real-time credit card fraud detection',
42
+ 'category': 'ml'
43
+ },
44
+ {
45
+ 'id': 'risk_analysis',
46
+ 'idea': 'Quantum Monte Carlo for Value-at-Risk (VaR) calculation on a derivatives portfolio',
47
+ 'category': 'risk'
48
+ },
49
+ {
50
+ 'id': 'credit_scoring',
51
+ 'idea': 'Variational quantum classifier for credit scoring using customer financial data',
52
+ 'category': 'ml'
53
+ }
54
+ ]
55
+
56
+
57
+ def run_resource_estimation_demo():
58
+ """Demonstrate quantum resource estimation capabilities."""
59
+ print("\n" + "=" * 60)
60
+ print("QUANTUM RESOURCE ESTIMATION DEMO")
61
+ print("=" * 60)
62
+
63
+ estimator = QuantumResourceEstimator('ibm_osprey')
64
+
65
+ # Portfolio optimization
66
+ print("\n1. QAOA for 50-Asset Portfolio (p=3 layers):")
67
+ print("-" * 50)
68
+ result = estimator.estimate_qaoa_resources(num_assets=50, p_layers=3)
69
+ for key, value in result.items():
70
+ print(f" {key}: {value}")
71
+
72
+ # Option pricing
73
+ print("\n2. Amplitude Estimation for Option Pricing (8-bit precision):")
74
+ print("-" * 50)
75
+ result = estimator.estimate_amplitude_estimation_resources(
76
+ precision_bits=8, num_qubits_oracle=20
77
+ )
78
+ for key, value in result.items():
79
+ print(f" {key}: {value}")
80
+
81
+ # Fraud detection
82
+ print("\n3. Grover's Search for Pattern Matching (1M records):")
83
+ print("-" * 50)
84
+ result = estimator.estimate_grover_resources(search_space_size=1_000_000)
85
+ for key, value in result.items():
86
+ print(f" {key}: {value}")
87
+
88
+
89
+ def run_classical_benchmark_demo():
90
+ """Demonstrate classical benchmarking capabilities."""
91
+ print("\n" + "=" * 60)
92
+ print("CLASSICAL BENCHMARK DEMO")
93
+ print("=" * 60)
94
+
95
+ print("\nCollecting financial data...")
96
+ data = collect_experiment_data(n_assets=15)
97
+ print(f"Loaded {data['n_observations']} days of data for {data['n_assets']} assets")
98
+
99
+ print("\nRunning classical portfolio optimization:")
100
+ print("-" * 50)
101
+ optimizer = ClassicalPortfolioOptimizer(
102
+ data['expected_returns'].values,
103
+ data['covariance_matrix'].values
104
+ )
105
+ result = optimizer.optimize_markowitz()
106
+ print(f" Expected Return: {result['expected_return']:.4f}")
107
+ print(f" Volatility: {result['volatility']:.4f}")
108
+ print(f" Sharpe Ratio: {result['sharpe_ratio']:.4f}")
109
+
110
+ print("\nTiming benchmark (100 runs):")
111
+ timing = optimizer.benchmark_timing(n_trials=100)
112
+ print(f" Mean time: {timing['mean_time_ms']:.3f} ms")
113
+ print(f" Std time: {timing['std_time_ms']:.3f} ms")
114
+
115
+
116
+ def run_crew_evaluation(idea: str, verbose: bool = True):
117
+ """Run the full crew evaluation on an idea."""
118
+ print("\n" + "=" * 60)
119
+ print("QUANTUM FINANCE FEASIBILITY ANALYSIS")
120
+ print("=" * 60)
121
+ print(f"\nIdea: {idea}")
122
+ print("-" * 60)
123
+
124
+ crew = QuantumFinanceCrew()
125
+ result = crew.evaluate(idea, verbose=verbose)
126
+
127
+ print("\n" + "=" * 60)
128
+ print("EVALUATION COMPLETE")
129
+ print("=" * 60)
130
+
131
+ return result
132
+
133
+
134
+ def run_batch_evaluation(verbose: bool = False):
135
+ """Run evaluation on all test cases."""
136
+ print("\n" + "=" * 60)
137
+ print("BATCH EVALUATION - ALL TEST CASES")
138
+ print("=" * 60)
139
+
140
+ crew = QuantumFinanceCrew()
141
+ metrics_collector = MetricsCollector()
142
+
143
+ results = []
144
+ for i, case in enumerate(TEST_CASES):
145
+ print(f"\n[{i+1}/{len(TEST_CASES)}] Evaluating: {case['id']}")
146
+ print(f" {case['idea'][:60]}...")
147
+
148
+ metrics = metrics_collector.start_evaluation(case['idea'])
149
+
150
+ try:
151
+ result = crew.evaluate(case['idea'], verbose=verbose)
152
+ metrics.total_agent_rounds = result.get('tasks_completed', 0)
153
+ result['case_id'] = case['id']
154
+ results.append(result)
155
+ except Exception as e:
156
+ print(f" ERROR: {e}")
157
+ result = {'case_id': case['id'], 'error': str(e)}
158
+ results.append(result)
159
+
160
+ metrics.complete()
161
+
162
+ print("\n" + "=" * 60)
163
+ print("BATCH EVALUATION SUMMARY")
164
+ print("=" * 60)
165
+ summary = metrics_collector.get_summary_statistics()
166
+ for key, value in summary.items():
167
+ print(f" {key}: {value}")
168
+
169
+ return results
170
+
171
+
172
+ def main():
173
+ parser = argparse.ArgumentParser(
174
+ description='Quantum Finance Feasibility Analysis Framework'
175
+ )
176
+ parser.add_argument(
177
+ '--idea', type=str,
178
+ help='Specific quantum finance idea to evaluate'
179
+ )
180
+ parser.add_argument(
181
+ '--batch', action='store_true',
182
+ help='Run batch evaluation on all test cases'
183
+ )
184
+ parser.add_argument(
185
+ '--demo', action='store_true',
186
+ help='Run resource estimation and benchmark demos'
187
+ )
188
+ parser.add_argument(
189
+ '--verbose', '-v', action='store_true',
190
+ help='Enable verbose output'
191
+ )
192
+
193
+ args = parser.parse_args()
194
+
195
+ if args.demo:
196
+ run_resource_estimation_demo()
197
+ run_classical_benchmark_demo()
198
+ elif args.batch:
199
+ run_batch_evaluation(verbose=args.verbose)
200
+ elif args.idea:
201
+ run_crew_evaluation(args.idea, verbose=args.verbose)
202
+ else:
203
+ # Default: run demo
204
+ print("Quantum Finance Feasibility Analysis Framework")
205
+ print("=" * 50)
206
+ print("\nUsage:")
207
+ print(" python main.py --demo # Resource estimation demos")
208
+ print(" python main.py --idea 'text' # Evaluate specific idea")
209
+ print(" python main.py --batch # Batch evaluate test cases")
210
+ print("\nRunning demo mode...")
211
+ run_resource_estimation_demo()
212
+ run_classical_benchmark_demo()
213
+
214
+
215
+ if __name__ == "__main__":
216
+ main()
requirements.txt ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Core framework
2
+ crewai>=1.7.0
3
+ crewai-tools>=1.7.0
4
+
5
+ # Quantum simulation
6
+ qiskit>=1.0.0
7
+ pennylane>=0.35.0
8
+
9
+ # Finance data and analysis
10
+ yfinance>=0.2.36
11
+ pandas>=2.0.0
12
+ numpy>=1.24.0
13
+ scipy>=1.10.0
14
+
15
+ # Visualization
16
+ matplotlib>=3.7.0
17
+
18
+ # Web interface
19
+ gradio>=4.0.0
20
+
21
+ # Utilities
22
+ pyyaml>=6.0
23
+ python-dotenv>=1.0.0
src/__init__.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Quantum Finance Feasibility Analysis Framework
3
+
4
+ An agentic AI framework for evaluating the feasibility of near-term
5
+ quantum computing applications in finance.
6
+ """
7
+
8
+ __version__ = "0.1.0"
src/quantum_finance_crew/__init__.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Quantum Finance Feasibility Crew
3
+
4
+ An agentic AI framework for evaluating the feasibility of near-term
5
+ quantum computing applications in finance.
6
+ """
7
+
8
+ from .crew import QuantumFinanceCrew
9
+
10
+ __version__ = "0.1.0"
11
+ __all__ = ["QuantumFinanceCrew"]
src/quantum_finance_crew/crew.py ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Main CrewAI implementation for quantum finance feasibility analysis.
3
+ """
4
+
5
+ import yaml
6
+ from pathlib import Path
7
+ from crewai import Agent, Crew, Task, Process
8
+
9
+
10
+ class QuantumFinanceCrew:
11
+ """
12
+ Multi-agent crew for evaluating quantum finance application feasibility.
13
+
14
+ This crew consists of four specialized agents:
15
+ - Quantum Algorithm Expert: Evaluates algorithm applicability and complexity
16
+ - Quantum Error Correction Expert: Assesses NISQ hardware constraints
17
+ - Classical Computing Expert: Benchmarks classical alternatives
18
+ - Finance Domain Expert: Evaluates business viability
19
+ """
20
+
21
+ def __init__(self, config_path: str = None):
22
+ """Initialize the crew with configuration."""
23
+ if config_path is None:
24
+ config_path = Path(__file__).parent.parent.parent / "config"
25
+ else:
26
+ config_path = Path(config_path)
27
+
28
+ self.agents_config = self._load_yaml(config_path / "agents.yaml")
29
+ self.tasks_config = self._load_yaml(config_path / "tasks.yaml")
30
+
31
+ self.agents = self._create_agents()
32
+ self.evaluation_history = []
33
+
34
+ def _load_yaml(self, path: Path) -> dict:
35
+ """Load YAML configuration file."""
36
+ with open(path, 'r') as f:
37
+ return yaml.safe_load(f)
38
+
39
+ def _create_agents(self) -> dict:
40
+ """Create all agents from configuration."""
41
+ agents = {}
42
+
43
+ for agent_name, config in self.agents_config.items():
44
+ agents[agent_name] = Agent(
45
+ role=config['role'],
46
+ goal=config['goal'],
47
+ backstory=config['backstory'],
48
+ verbose=config.get('verbose', True),
49
+ allow_delegation=config.get('allow_delegation', True)
50
+ )
51
+
52
+ return agents
53
+
54
+ def _create_tasks(self, idea: str) -> list:
55
+ """Create tasks for evaluating a specific idea."""
56
+ tasks = []
57
+ task_objects = {}
58
+
59
+ # Create tasks in order (context dependencies handled)
60
+ task_order = [
61
+ 'analyze_quantum_feasibility',
62
+ 'assess_nisq_constraints',
63
+ 'benchmark_classical_alternatives',
64
+ 'evaluate_business_viability',
65
+ 'synthesize_final_assessment'
66
+ ]
67
+
68
+ for task_name in task_order:
69
+ config = self.tasks_config[task_name]
70
+ agent_name = config['agent']
71
+
72
+ # Build context from previous tasks if specified
73
+ context = []
74
+ if 'context' in config:
75
+ context = [task_objects[ctx] for ctx in config['context'] if ctx in task_objects]
76
+
77
+ task = Task(
78
+ description=config['description'].format(idea=idea),
79
+ expected_output=config['expected_output'],
80
+ agent=self.agents[agent_name],
81
+ context=context if context else None
82
+ )
83
+
84
+ task_objects[task_name] = task
85
+ tasks.append(task)
86
+
87
+ return tasks
88
+
89
+ def evaluate(self, idea: str, verbose: bool = True) -> dict:
90
+ """
91
+ Evaluate a quantum finance application idea.
92
+
93
+ Args:
94
+ idea: Description of the proposed quantum finance application
95
+ verbose: Whether to print detailed progress
96
+
97
+ Returns:
98
+ Dictionary containing the evaluation results and metrics
99
+ """
100
+ tasks = self._create_tasks(idea)
101
+
102
+ crew = Crew(
103
+ agents=list(self.agents.values()),
104
+ tasks=tasks,
105
+ process=Process.sequential,
106
+ verbose=verbose
107
+ )
108
+
109
+ result = crew.kickoff()
110
+
111
+ # Store evaluation in history
112
+ evaluation = {
113
+ 'idea': idea,
114
+ 'result': result,
115
+ 'tasks_completed': len(tasks)
116
+ }
117
+ self.evaluation_history.append(evaluation)
118
+
119
+ return evaluation
120
+
121
+ def batch_evaluate(self, ideas: list, verbose: bool = False) -> list:
122
+ """
123
+ Evaluate multiple quantum finance application ideas.
124
+
125
+ Args:
126
+ ideas: List of idea descriptions to evaluate
127
+ verbose: Whether to print detailed progress
128
+
129
+ Returns:
130
+ List of evaluation results
131
+ """
132
+ results = []
133
+ for i, idea in enumerate(ideas):
134
+ print(f"\n{'='*60}")
135
+ print(f"Evaluating idea {i+1}/{len(ideas)}: {idea[:50]}...")
136
+ print('='*60)
137
+
138
+ result = self.evaluate(idea, verbose=verbose)
139
+ results.append(result)
140
+
141
+ return results
142
+
143
+ def get_evaluation_summary(self) -> dict:
144
+ """Get summary statistics of all evaluations."""
145
+ return {
146
+ 'total_evaluations': len(self.evaluation_history),
147
+ 'ideas_evaluated': [e['idea'] for e in self.evaluation_history]
148
+ }
149
+
150
+
151
+ def main():
152
+ """Example usage of the QuantumFinanceCrew."""
153
+ crew = QuantumFinanceCrew()
154
+
155
+ # Example finance use cases to evaluate
156
+ test_ideas = [
157
+ "Quantum portfolio optimization using QAOA for a 100-asset portfolio",
158
+ "Quantum Monte Carlo for option pricing on European call options",
159
+ "Quantum machine learning for credit card fraud detection"
160
+ ]
161
+
162
+ # Evaluate first idea as demo
163
+ print("Quantum Finance Feasibility Analysis Framework")
164
+ print("=" * 50)
165
+ print(f"\nEvaluating: {test_ideas[0]}")
166
+
167
+ result = crew.evaluate(test_ideas[0])
168
+ print("\n" + "=" * 50)
169
+ print("EVALUATION COMPLETE")
170
+ print("=" * 50)
171
+
172
+
173
+ if __name__ == "__main__":
174
+ main()
src/tools/__init__.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Tools for quantum finance feasibility analysis.
3
+ """
4
+
5
+ from .quantum_tools import (
6
+ QuantumResourceEstimator,
7
+ NISQNoiseModel,
8
+ run_qaoa_simulation
9
+ )
10
+ from .finance_tools import (
11
+ FinanceDataCollector,
12
+ ClassicalPortfolioOptimizer,
13
+ OptionPricer,
14
+ collect_experiment_data
15
+ )
16
+
17
+ __all__ = [
18
+ 'QuantumResourceEstimator',
19
+ 'NISQNoiseModel',
20
+ 'run_qaoa_simulation',
21
+ 'FinanceDataCollector',
22
+ 'ClassicalPortfolioOptimizer',
23
+ 'OptionPricer',
24
+ 'collect_experiment_data'
25
+ ]
src/tools/finance_tools.py ADDED
@@ -0,0 +1,365 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Finance data tools using Yahoo Finance and analysis utilities.
3
+
4
+ Provides utilities for:
5
+ - Historical price data retrieval
6
+ - Portfolio optimization benchmarks
7
+ - Option pricing models
8
+ - Risk metrics calculation
9
+ """
10
+
11
+ import numpy as np
12
+ import pandas as pd
13
+ from datetime import datetime, timedelta
14
+ from typing import Optional
15
+
16
+
17
+ class FinanceDataCollector:
18
+ """Collect and process financial data for quantum finance experiments."""
19
+
20
+ # Default benchmark assets
21
+ DEFAULT_TICKERS = [
22
+ 'AAPL', 'MSFT', 'GOOGL', 'AMZN', 'META', # Tech
23
+ 'JPM', 'BAC', 'GS', 'MS', 'C', # Finance
24
+ 'JNJ', 'PFE', 'UNH', 'MRK', 'ABBV', # Healthcare
25
+ 'XOM', 'CVX', 'COP', 'SLB', 'EOG', # Energy
26
+ 'PG', 'KO', 'PEP', 'WMT', 'COST' # Consumer
27
+ ]
28
+
29
+ def __init__(self, tickers: Optional[list] = None):
30
+ """Initialize with list of tickers to track."""
31
+ self.tickers = tickers or self.DEFAULT_TICKERS
32
+
33
+ def fetch_historical_data(
34
+ self,
35
+ start_date: str = None,
36
+ end_date: str = None,
37
+ period: str = "1y"
38
+ ) -> pd.DataFrame:
39
+ """
40
+ Fetch historical price data using yfinance.
41
+
42
+ Args:
43
+ start_date: Start date (YYYY-MM-DD format)
44
+ end_date: End date (YYYY-MM-DD format)
45
+ period: Alternative to start/end - e.g., "1y", "6mo", "1mo"
46
+
47
+ Returns:
48
+ DataFrame with adjusted close prices
49
+ """
50
+ try:
51
+ import yfinance as yf
52
+
53
+ if start_date and end_date:
54
+ data = yf.download(
55
+ self.tickers,
56
+ start=start_date,
57
+ end=end_date,
58
+ progress=False
59
+ )
60
+ else:
61
+ data = yf.download(
62
+ self.tickers,
63
+ period=period,
64
+ progress=False
65
+ )
66
+
67
+ # Extract adjusted close prices
68
+ if len(data) == 0:
69
+ print("No data from yfinance, using synthetic data...")
70
+ return self._generate_synthetic_data()
71
+
72
+ if 'Adj Close' in data.columns.get_level_values(0):
73
+ prices = data['Adj Close']
74
+ else:
75
+ prices = data['Close']
76
+
77
+ # If prices are empty, use synthetic
78
+ if prices.empty or prices.isna().all().all():
79
+ print("Empty price data, using synthetic data...")
80
+ return self._generate_synthetic_data()
81
+
82
+ return prices
83
+
84
+ except (ImportError, Exception) as e:
85
+ print(f"yfinance error ({e}), using synthetic data...")
86
+ return self._generate_synthetic_data()
87
+
88
+ def _generate_synthetic_data(self, days: int = 252) -> pd.DataFrame:
89
+ """Generate synthetic price data for testing when yfinance unavailable."""
90
+ np.random.seed(42)
91
+ dates = pd.date_range(end=datetime.now(), periods=days, freq='D')
92
+
93
+ data = {}
94
+ for ticker in self.tickers:
95
+ # Geometric Brownian Motion simulation
96
+ initial_price = np.random.uniform(50, 500)
97
+ returns = np.random.normal(0.0005, 0.02, days)
98
+ prices = initial_price * np.cumprod(1 + returns)
99
+ data[ticker] = prices
100
+
101
+ return pd.DataFrame(data, index=dates)
102
+
103
+ def calculate_returns(self, prices: pd.DataFrame) -> pd.DataFrame:
104
+ """Calculate daily returns from price data."""
105
+ return prices.pct_change(fill_method=None).dropna()
106
+
107
+ def calculate_covariance_matrix(self, returns: pd.DataFrame) -> pd.DataFrame:
108
+ """Calculate annualized covariance matrix."""
109
+ return returns.cov() * 252 # Annualize
110
+
111
+ def calculate_expected_returns(self, returns: pd.DataFrame) -> pd.Series:
112
+ """Calculate annualized expected returns."""
113
+ return returns.mean() * 252 # Annualize
114
+
115
+
116
+ class ClassicalPortfolioOptimizer:
117
+ """Classical portfolio optimization for benchmarking quantum approaches."""
118
+
119
+ def __init__(self, expected_returns: np.ndarray, covariance_matrix: np.ndarray):
120
+ """
121
+ Initialize optimizer.
122
+
123
+ Args:
124
+ expected_returns: Expected returns vector
125
+ covariance_matrix: Covariance matrix of returns
126
+ """
127
+ self.mu = expected_returns
128
+ self.sigma = covariance_matrix
129
+ self.n_assets = len(expected_returns)
130
+
131
+ def optimize_markowitz(self, target_return: float = None) -> dict:
132
+ """
133
+ Solve Markowitz mean-variance optimization.
134
+
135
+ Args:
136
+ target_return: Target portfolio return (if None, maximize Sharpe)
137
+
138
+ Returns:
139
+ Optimization results
140
+ """
141
+ try:
142
+ from scipy.optimize import minimize
143
+
144
+ def portfolio_volatility(weights):
145
+ return np.sqrt(weights @ self.sigma @ weights)
146
+
147
+ def negative_sharpe(weights):
148
+ ret = weights @ self.mu
149
+ vol = portfolio_volatility(weights)
150
+ return -ret / vol if vol > 0 else 0
151
+
152
+ # Constraints: weights sum to 1, all weights >= 0
153
+ constraints = [{'type': 'eq', 'fun': lambda w: np.sum(w) - 1}]
154
+ bounds = [(0, 1) for _ in range(self.n_assets)]
155
+
156
+ # Initial guess: equal weights
157
+ w0 = np.ones(self.n_assets) / self.n_assets
158
+
159
+ if target_return is not None:
160
+ constraints.append({
161
+ 'type': 'eq',
162
+ 'fun': lambda w: w @ self.mu - target_return
163
+ })
164
+ result = minimize(
165
+ portfolio_volatility, w0,
166
+ method='SLSQP', bounds=bounds, constraints=constraints
167
+ )
168
+ else:
169
+ result = minimize(
170
+ negative_sharpe, w0,
171
+ method='SLSQP', bounds=bounds, constraints=constraints
172
+ )
173
+
174
+ optimal_weights = result.x
175
+ portfolio_return = optimal_weights @ self.mu
176
+ portfolio_vol = portfolio_volatility(optimal_weights)
177
+ sharpe = portfolio_return / portfolio_vol if portfolio_vol > 0 else 0
178
+
179
+ return {
180
+ 'weights': optimal_weights,
181
+ 'expected_return': portfolio_return,
182
+ 'volatility': portfolio_vol,
183
+ 'sharpe_ratio': sharpe,
184
+ 'optimization_success': result.success,
185
+ 'solver': 'scipy.optimize.minimize (SLSQP)'
186
+ }
187
+
188
+ except ImportError:
189
+ return {'error': 'scipy not available'}
190
+
191
+ def benchmark_timing(self, n_trials: int = 100) -> dict:
192
+ """
193
+ Benchmark classical optimization timing.
194
+
195
+ Args:
196
+ n_trials: Number of optimization runs
197
+
198
+ Returns:
199
+ Timing statistics
200
+ """
201
+ import time
202
+
203
+ times = []
204
+ for _ in range(n_trials):
205
+ start = time.perf_counter()
206
+ self.optimize_markowitz()
207
+ times.append(time.perf_counter() - start)
208
+
209
+ return {
210
+ 'n_assets': self.n_assets,
211
+ 'n_trials': n_trials,
212
+ 'mean_time_ms': np.mean(times) * 1000,
213
+ 'std_time_ms': np.std(times) * 1000,
214
+ 'min_time_ms': np.min(times) * 1000,
215
+ 'max_time_ms': np.max(times) * 1000
216
+ }
217
+
218
+
219
+ class OptionPricer:
220
+ """Classical option pricing for benchmarking quantum amplitude estimation."""
221
+
222
+ @staticmethod
223
+ def black_scholes_call(S: float, K: float, T: float, r: float, sigma: float) -> float:
224
+ """
225
+ Black-Scholes European call option price.
226
+
227
+ Args:
228
+ S: Current stock price
229
+ K: Strike price
230
+ T: Time to maturity (years)
231
+ r: Risk-free rate
232
+ sigma: Volatility
233
+
234
+ Returns:
235
+ Call option price
236
+ """
237
+ from scipy.stats import norm
238
+
239
+ d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T))
240
+ d2 = d1 - sigma*np.sqrt(T)
241
+
242
+ return S * norm.cdf(d1) - K * np.exp(-r*T) * norm.cdf(d2)
243
+
244
+ @staticmethod
245
+ def monte_carlo_call(
246
+ S: float, K: float, T: float, r: float, sigma: float,
247
+ n_paths: int = 100000
248
+ ) -> dict:
249
+ """
250
+ Monte Carlo European call option pricing.
251
+
252
+ Args:
253
+ S: Current stock price
254
+ K: Strike price
255
+ T: Time to maturity (years)
256
+ r: Risk-free rate
257
+ sigma: Volatility
258
+ n_paths: Number of simulation paths
259
+
260
+ Returns:
261
+ Price estimate with confidence interval
262
+ """
263
+ np.random.seed(42)
264
+
265
+ # Simulate terminal prices
266
+ Z = np.random.standard_normal(n_paths)
267
+ ST = S * np.exp((r - 0.5*sigma**2)*T + sigma*np.sqrt(T)*Z)
268
+
269
+ # Calculate payoffs
270
+ payoffs = np.maximum(ST - K, 0)
271
+ discounted = np.exp(-r*T) * payoffs
272
+
273
+ price = np.mean(discounted)
274
+ std_error = np.std(discounted) / np.sqrt(n_paths)
275
+
276
+ return {
277
+ 'price': price,
278
+ 'std_error': std_error,
279
+ 'confidence_interval_95': (price - 1.96*std_error, price + 1.96*std_error),
280
+ 'n_paths': n_paths
281
+ }
282
+
283
+ @staticmethod
284
+ def benchmark_monte_carlo_timing(
285
+ n_paths_list: list = None,
286
+ n_trials: int = 10
287
+ ) -> list:
288
+ """Benchmark Monte Carlo timing for different path counts."""
289
+ import time
290
+
291
+ if n_paths_list is None:
292
+ n_paths_list = [1000, 10000, 100000, 1000000]
293
+
294
+ results = []
295
+ for n_paths in n_paths_list:
296
+ times = []
297
+ for _ in range(n_trials):
298
+ start = time.perf_counter()
299
+ OptionPricer.monte_carlo_call(
300
+ S=100, K=100, T=1, r=0.05, sigma=0.2,
301
+ n_paths=n_paths
302
+ )
303
+ times.append(time.perf_counter() - start)
304
+
305
+ results.append({
306
+ 'n_paths': n_paths,
307
+ 'mean_time_ms': np.mean(times) * 1000,
308
+ 'std_time_ms': np.std(times) * 1000
309
+ })
310
+
311
+ return results
312
+
313
+
314
+ def collect_experiment_data(n_assets: int = 25) -> dict:
315
+ """
316
+ Collect data for quantum finance experiments.
317
+
318
+ Args:
319
+ n_assets: Number of assets to include
320
+
321
+ Returns:
322
+ Dictionary with prices, returns, and optimization inputs
323
+ """
324
+ collector = FinanceDataCollector(
325
+ tickers=FinanceDataCollector.DEFAULT_TICKERS[:n_assets]
326
+ )
327
+
328
+ print(f"Fetching data for {n_assets} assets...")
329
+ prices = collector.fetch_historical_data(period="1y")
330
+ returns = collector.calculate_returns(prices)
331
+ cov_matrix = collector.calculate_covariance_matrix(returns)
332
+ exp_returns = collector.calculate_expected_returns(returns)
333
+
334
+ return {
335
+ 'prices': prices,
336
+ 'returns': returns,
337
+ 'covariance_matrix': cov_matrix,
338
+ 'expected_returns': exp_returns,
339
+ 'n_assets': n_assets,
340
+ 'n_observations': len(returns)
341
+ }
342
+
343
+
344
+ if __name__ == "__main__":
345
+ # Demo data collection and classical benchmarking
346
+ print("Finance Data Collection Demo")
347
+ print("=" * 50)
348
+
349
+ data = collect_experiment_data(n_assets=10)
350
+ print(f"Collected {data['n_observations']} days of data for {data['n_assets']} assets")
351
+
352
+ print("\nClassical Portfolio Optimization:")
353
+ print("-" * 50)
354
+ optimizer = ClassicalPortfolioOptimizer(
355
+ data['expected_returns'].values,
356
+ data['covariance_matrix'].values
357
+ )
358
+ result = optimizer.optimize_markowitz()
359
+ print(f"Expected Return: {result['expected_return']:.4f}")
360
+ print(f"Volatility: {result['volatility']:.4f}")
361
+ print(f"Sharpe Ratio: {result['sharpe_ratio']:.4f}")
362
+
363
+ print("\nOptimization Timing Benchmark:")
364
+ timing = optimizer.benchmark_timing(n_trials=100)
365
+ print(f"Mean time: {timing['mean_time_ms']:.3f} ms")
src/tools/quantum_tools.py ADDED
@@ -0,0 +1,365 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Quantum simulation tools using Qiskit and PennyLane.
3
+
4
+ Provides utilities for:
5
+ - QAOA circuit simulation
6
+ - VQE implementations
7
+ - Noise modeling for NISQ assessment
8
+ - Resource estimation
9
+ """
10
+
11
+ import numpy as np
12
+ from typing import Optional
13
+
14
+
15
+ class QuantumResourceEstimator:
16
+ """Estimate quantum resources required for finance applications."""
17
+
18
+ # Current NISQ hardware constraints (2024-2026 estimates)
19
+ HARDWARE_SPECS = {
20
+ 'ibm_osprey': {
21
+ 'qubits': 433,
22
+ 'gate_fidelity_1q': 0.9996,
23
+ 'gate_fidelity_2q': 0.99,
24
+ 'coherence_time_us': 100,
25
+ 'gate_time_1q_ns': 35,
26
+ 'gate_time_2q_ns': 300,
27
+ },
28
+ 'ibm_condor': {
29
+ 'qubits': 1121,
30
+ 'gate_fidelity_1q': 0.9995,
31
+ 'gate_fidelity_2q': 0.985,
32
+ 'coherence_time_us': 80,
33
+ 'gate_time_1q_ns': 35,
34
+ 'gate_time_2q_ns': 300,
35
+ },
36
+ 'ionq_forte': {
37
+ 'qubits': 36,
38
+ 'gate_fidelity_1q': 0.9999,
39
+ 'gate_fidelity_2q': 0.995,
40
+ 'coherence_time_us': 10000000, # Ion traps have very long coherence
41
+ 'gate_time_1q_ns': 10000,
42
+ 'gate_time_2q_ns': 200000,
43
+ },
44
+ 'google_sycamore': {
45
+ 'qubits': 72,
46
+ 'gate_fidelity_1q': 0.9985,
47
+ 'gate_fidelity_2q': 0.995,
48
+ 'coherence_time_us': 20,
49
+ 'gate_time_1q_ns': 25,
50
+ 'gate_time_2q_ns': 32,
51
+ }
52
+ }
53
+
54
+ def __init__(self, hardware: str = 'ibm_osprey'):
55
+ """Initialize with target hardware specifications."""
56
+ if hardware not in self.HARDWARE_SPECS:
57
+ raise ValueError(f"Unknown hardware: {hardware}. Choose from {list(self.HARDWARE_SPECS.keys())}")
58
+ self.hardware = hardware
59
+ self.specs = self.HARDWARE_SPECS[hardware]
60
+
61
+ def estimate_qaoa_resources(self, num_assets: int, p_layers: int = 1) -> dict:
62
+ """
63
+ Estimate resources for QAOA portfolio optimization.
64
+
65
+ Args:
66
+ num_assets: Number of assets in portfolio
67
+ p_layers: Number of QAOA layers (depth parameter)
68
+
69
+ Returns:
70
+ Dictionary with resource estimates
71
+ """
72
+ # QAOA for portfolio optimization typically requires n qubits for n assets
73
+ qubits_required = num_assets
74
+
75
+ # Gates per layer: roughly O(n^2) for cost Hamiltonian + O(n) for mixer
76
+ two_qubit_gates_per_layer = num_assets * (num_assets - 1) // 2
77
+ one_qubit_gates_per_layer = num_assets * 2
78
+
79
+ total_2q_gates = two_qubit_gates_per_layer * p_layers
80
+ total_1q_gates = one_qubit_gates_per_layer * p_layers
81
+
82
+ # Circuit depth estimate
83
+ circuit_depth = p_layers * (num_assets + 2)
84
+
85
+ # Total execution time
86
+ exec_time_ns = (total_1q_gates * self.specs['gate_time_1q_ns'] +
87
+ total_2q_gates * self.specs['gate_time_2q_ns'])
88
+ exec_time_us = exec_time_ns / 1000
89
+
90
+ # Error probability estimate
91
+ success_prob = (self.specs['gate_fidelity_1q'] ** total_1q_gates *
92
+ self.specs['gate_fidelity_2q'] ** total_2q_gates)
93
+
94
+ # Feasibility check
95
+ feasible = (
96
+ qubits_required <= self.specs['qubits'] and
97
+ exec_time_us < self.specs['coherence_time_us'] and
98
+ success_prob > 0.01 # At least 1% success probability
99
+ )
100
+
101
+ return {
102
+ 'qubits_required': qubits_required,
103
+ 'qubits_available': self.specs['qubits'],
104
+ 'total_1q_gates': total_1q_gates,
105
+ 'total_2q_gates': total_2q_gates,
106
+ 'circuit_depth': circuit_depth,
107
+ 'execution_time_us': exec_time_us,
108
+ 'coherence_time_us': self.specs['coherence_time_us'],
109
+ 'success_probability': success_prob,
110
+ 'feasible_on_hardware': feasible,
111
+ 'bottleneck': self._identify_bottleneck(
112
+ qubits_required, exec_time_us, success_prob
113
+ )
114
+ }
115
+
116
+ def estimate_amplitude_estimation_resources(
117
+ self,
118
+ precision_bits: int,
119
+ num_qubits_oracle: int
120
+ ) -> dict:
121
+ """
122
+ Estimate resources for quantum amplitude estimation (option pricing).
123
+
124
+ Args:
125
+ precision_bits: Number of bits of precision required
126
+ num_qubits_oracle: Qubits needed for the oracle (problem encoding)
127
+
128
+ Returns:
129
+ Dictionary with resource estimates
130
+ """
131
+ # Total qubits: oracle + precision register
132
+ qubits_required = num_qubits_oracle + precision_bits
133
+
134
+ # Amplitude estimation requires O(2^precision) oracle calls
135
+ oracle_calls = 2 ** precision_bits
136
+
137
+ # Assume oracle has O(n^2) gates
138
+ gates_per_oracle = num_qubits_oracle ** 2
139
+ total_2q_gates = oracle_calls * gates_per_oracle
140
+
141
+ # Execution time
142
+ exec_time_us = (total_2q_gates * self.specs['gate_time_2q_ns']) / 1000
143
+
144
+ # Success probability
145
+ success_prob = self.specs['gate_fidelity_2q'] ** total_2q_gates
146
+
147
+ feasible = (
148
+ qubits_required <= self.specs['qubits'] and
149
+ exec_time_us < self.specs['coherence_time_us'] * 0.5 and
150
+ success_prob > 0.001
151
+ )
152
+
153
+ return {
154
+ 'qubits_required': qubits_required,
155
+ 'qubits_available': self.specs['qubits'],
156
+ 'oracle_calls': oracle_calls,
157
+ 'total_2q_gates': total_2q_gates,
158
+ 'execution_time_us': exec_time_us,
159
+ 'coherence_time_us': self.specs['coherence_time_us'],
160
+ 'success_probability': success_prob,
161
+ 'feasible_on_hardware': feasible,
162
+ 'bottleneck': self._identify_bottleneck(
163
+ qubits_required, exec_time_us, success_prob
164
+ )
165
+ }
166
+
167
+ def estimate_grover_resources(self, search_space_size: int) -> dict:
168
+ """
169
+ Estimate resources for Grover's search (fraud detection).
170
+
171
+ Args:
172
+ search_space_size: Size of search space N
173
+
174
+ Returns:
175
+ Dictionary with resource estimates
176
+ """
177
+ # Qubits: log2(N) for encoding
178
+ qubits_required = int(np.ceil(np.log2(search_space_size)))
179
+
180
+ # Grover iterations: O(sqrt(N))
181
+ iterations = int(np.ceil(np.sqrt(search_space_size) * np.pi / 4))
182
+
183
+ # Gates per iteration: O(n) for oracle + O(n) for diffusion
184
+ gates_per_iteration = qubits_required * 4
185
+ total_2q_gates = iterations * gates_per_iteration
186
+
187
+ exec_time_us = (total_2q_gates * self.specs['gate_time_2q_ns']) / 1000
188
+ success_prob = self.specs['gate_fidelity_2q'] ** total_2q_gates
189
+
190
+ feasible = (
191
+ qubits_required <= self.specs['qubits'] and
192
+ exec_time_us < self.specs['coherence_time_us'] and
193
+ success_prob > 0.01
194
+ )
195
+
196
+ return {
197
+ 'qubits_required': qubits_required,
198
+ 'qubits_available': self.specs['qubits'],
199
+ 'grover_iterations': iterations,
200
+ 'total_2q_gates': total_2q_gates,
201
+ 'execution_time_us': exec_time_us,
202
+ 'coherence_time_us': self.specs['coherence_time_us'],
203
+ 'success_probability': success_prob,
204
+ 'feasible_on_hardware': feasible,
205
+ 'classical_speedup': f"O(sqrt(N)) vs O(N)",
206
+ 'bottleneck': self._identify_bottleneck(
207
+ qubits_required, exec_time_us, success_prob
208
+ )
209
+ }
210
+
211
+ def _identify_bottleneck(
212
+ self,
213
+ qubits_required: int,
214
+ exec_time_us: float,
215
+ success_prob: float
216
+ ) -> str:
217
+ """Identify the primary bottleneck for feasibility."""
218
+ bottlenecks = []
219
+
220
+ if qubits_required > self.specs['qubits']:
221
+ bottlenecks.append(f"Qubit count ({qubits_required} > {self.specs['qubits']})")
222
+
223
+ if exec_time_us > self.specs['coherence_time_us']:
224
+ ratio = exec_time_us / self.specs['coherence_time_us']
225
+ bottlenecks.append(f"Coherence time (circuit {ratio:.1f}x longer than coherence)")
226
+
227
+ if success_prob < 0.01:
228
+ bottlenecks.append(f"Gate errors (success prob {success_prob:.2e})")
229
+
230
+ return "; ".join(bottlenecks) if bottlenecks else "None - appears feasible"
231
+
232
+
233
+ class NISQNoiseModel:
234
+ """Model noise effects on NISQ quantum circuits."""
235
+
236
+ def __init__(self, depolarizing_rate: float = 0.01, measurement_error: float = 0.02):
237
+ """
238
+ Initialize noise model.
239
+
240
+ Args:
241
+ depolarizing_rate: Single-qubit depolarizing error rate
242
+ measurement_error: Measurement error probability
243
+ """
244
+ self.depolarizing_rate = depolarizing_rate
245
+ self.measurement_error = measurement_error
246
+
247
+ def estimate_output_fidelity(self, num_gates: int, num_qubits: int) -> float:
248
+ """
249
+ Estimate output state fidelity after noisy circuit execution.
250
+
251
+ Args:
252
+ num_gates: Total number of gates in circuit
253
+ num_qubits: Number of qubits
254
+
255
+ Returns:
256
+ Estimated fidelity (0 to 1)
257
+ """
258
+ # Simplified noise model: each gate reduces fidelity
259
+ gate_fidelity = (1 - self.depolarizing_rate) ** num_gates
260
+
261
+ # Measurement errors
262
+ meas_fidelity = (1 - self.measurement_error) ** num_qubits
263
+
264
+ return gate_fidelity * meas_fidelity
265
+
266
+ def required_shots_for_precision(
267
+ self,
268
+ target_precision: float,
269
+ success_probability: float
270
+ ) -> int:
271
+ """
272
+ Calculate required measurement shots for target precision.
273
+
274
+ Args:
275
+ target_precision: Desired precision (e.g., 0.01 for 1%)
276
+ success_probability: Probability of successful circuit execution
277
+
278
+ Returns:
279
+ Number of shots required
280
+ """
281
+ # Using Hoeffding bound: shots >= 1/(2 * precision^2 * success_prob)
282
+ if success_probability < 1e-10:
283
+ return float('inf')
284
+
285
+ shots = int(np.ceil(1 / (2 * target_precision**2 * success_probability)))
286
+ return min(shots, 10**9) # Cap at 1 billion shots
287
+
288
+
289
+ def run_qaoa_simulation(num_assets: int = 10, p_layers: int = 1) -> dict:
290
+ """
291
+ Run a simplified QAOA simulation for portfolio optimization.
292
+
293
+ This is a demonstration of the simulation capability.
294
+ Full implementation would use Qiskit or PennyLane.
295
+
296
+ Args:
297
+ num_assets: Number of assets
298
+ p_layers: QAOA depth
299
+
300
+ Returns:
301
+ Simulation results
302
+ """
303
+ try:
304
+ import pennylane as qml
305
+
306
+ # Create a simple QAOA-style circuit
307
+ dev = qml.device('default.qubit', wires=min(num_assets, 10))
308
+
309
+ @qml.qnode(dev)
310
+ def qaoa_circuit(gamma, beta):
311
+ # Initial superposition
312
+ for i in range(min(num_assets, 10)):
313
+ qml.Hadamard(wires=i)
314
+
315
+ # Simplified cost layer
316
+ for i in range(min(num_assets, 10) - 1):
317
+ qml.CNOT(wires=[i, i+1])
318
+ qml.RZ(gamma, wires=i+1)
319
+ qml.CNOT(wires=[i, i+1])
320
+
321
+ # Mixer layer
322
+ for i in range(min(num_assets, 10)):
323
+ qml.RX(beta, wires=i)
324
+
325
+ return qml.expval(qml.PauliZ(0))
326
+
327
+ # Run with sample parameters
328
+ result = qaoa_circuit(0.5, 0.3)
329
+
330
+ return {
331
+ 'status': 'success',
332
+ 'expectation_value': float(result),
333
+ 'num_qubits_used': min(num_assets, 10),
334
+ 'simulator': 'pennylane.default.qubit'
335
+ }
336
+
337
+ except ImportError:
338
+ return {
339
+ 'status': 'pennylane_not_available',
340
+ 'message': 'PennyLane not installed. Install with: pip install pennylane'
341
+ }
342
+ except Exception as e:
343
+ return {
344
+ 'status': 'error',
345
+ 'message': str(e)
346
+ }
347
+
348
+
349
+ if __name__ == "__main__":
350
+ # Demo resource estimation
351
+ estimator = QuantumResourceEstimator('ibm_osprey')
352
+
353
+ print("QAOA Resource Estimation for 50-asset portfolio:")
354
+ print("-" * 50)
355
+ result = estimator.estimate_qaoa_resources(num_assets=50, p_layers=3)
356
+ for key, value in result.items():
357
+ print(f" {key}: {value}")
358
+
359
+ print("\nAmplitude Estimation for Option Pricing (8-bit precision):")
360
+ print("-" * 50)
361
+ result = estimator.estimate_amplitude_estimation_resources(
362
+ precision_bits=8, num_qubits_oracle=20
363
+ )
364
+ for key, value in result.items():
365
+ print(f" {key}: {value}")
src/utils/__init__.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Utility modules for quantum finance framework.
3
+ """
4
+
5
+ from .evaluation import (
6
+ EvaluationMetrics,
7
+ MetricsCollector,
8
+ HallucinationChecker,
9
+ calculate_expert_alignment,
10
+ extract_scores_from_text,
11
+ LITERATURE_CONSENSUS
12
+ )
13
+
14
+ __all__ = [
15
+ 'EvaluationMetrics',
16
+ 'MetricsCollector',
17
+ 'HallucinationChecker',
18
+ 'calculate_expert_alignment',
19
+ 'extract_scores_from_text',
20
+ 'LITERATURE_CONSENSUS'
21
+ ]
src/utils/evaluation.py ADDED
@@ -0,0 +1,377 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Evaluation metrics for the quantum finance feasibility framework.
3
+
4
+ Metrics defined per plan.md:
5
+ 1. Expert Alignment: Agreement with literature/expert consensus
6
+ 2. Hallucination Rate: Factual accuracy of agent outputs
7
+ 3. Computational Efficiency: Agent rounds and time per evaluation
8
+ """
9
+
10
+ import re
11
+ import time
12
+ from dataclasses import dataclass, field
13
+ from typing import Optional
14
+ from datetime import datetime
15
+
16
+
17
+ @dataclass
18
+ class EvaluationMetrics:
19
+ """Container for evaluation metrics of a single run."""
20
+ idea: str
21
+ start_time: datetime = field(default_factory=datetime.now)
22
+ end_time: Optional[datetime] = None
23
+
24
+ # Computational efficiency metrics
25
+ total_agent_rounds: int = 0
26
+ total_tokens_used: int = 0
27
+ wall_clock_time_seconds: float = 0.0
28
+
29
+ # Quality metrics (to be assessed manually or via comparison)
30
+ expert_alignment_score: Optional[float] = None # 0-1 scale
31
+ hallucination_count: int = 0
32
+ factual_claims_count: int = 0
33
+
34
+ # Output scores from agents
35
+ quantum_feasibility_score: Optional[float] = None
36
+ hardware_readiness_score: Optional[float] = None
37
+ classical_competitiveness_score: Optional[float] = None
38
+ business_viability_score: Optional[float] = None
39
+ overall_score: Optional[float] = None
40
+
41
+ def complete(self):
42
+ """Mark evaluation as complete and calculate duration."""
43
+ self.end_time = datetime.now()
44
+ self.wall_clock_time_seconds = (self.end_time - self.start_time).total_seconds()
45
+
46
+ @property
47
+ def hallucination_rate(self) -> Optional[float]:
48
+ """Calculate hallucination rate as fraction of factual claims."""
49
+ if self.factual_claims_count == 0:
50
+ return None
51
+ return self.hallucination_count / self.factual_claims_count
52
+
53
+ def to_dict(self) -> dict:
54
+ """Convert to dictionary for serialization."""
55
+ return {
56
+ 'idea': self.idea,
57
+ 'start_time': self.start_time.isoformat(),
58
+ 'end_time': self.end_time.isoformat() if self.end_time else None,
59
+ 'total_agent_rounds': self.total_agent_rounds,
60
+ 'total_tokens_used': self.total_tokens_used,
61
+ 'wall_clock_time_seconds': self.wall_clock_time_seconds,
62
+ 'expert_alignment_score': self.expert_alignment_score,
63
+ 'hallucination_rate': self.hallucination_rate,
64
+ 'quantum_feasibility_score': self.quantum_feasibility_score,
65
+ 'hardware_readiness_score': self.hardware_readiness_score,
66
+ 'classical_competitiveness_score': self.classical_competitiveness_score,
67
+ 'business_viability_score': self.business_viability_score,
68
+ 'overall_score': self.overall_score
69
+ }
70
+
71
+
72
+ class MetricsCollector:
73
+ """Collect and aggregate metrics across multiple evaluations."""
74
+
75
+ def __init__(self):
76
+ self.evaluations: list[EvaluationMetrics] = []
77
+
78
+ def start_evaluation(self, idea: str) -> EvaluationMetrics:
79
+ """Start tracking a new evaluation."""
80
+ metrics = EvaluationMetrics(idea=idea)
81
+ self.evaluations.append(metrics)
82
+ return metrics
83
+
84
+ def get_summary_statistics(self) -> dict:
85
+ """Calculate summary statistics across all evaluations."""
86
+ if not self.evaluations:
87
+ return {'error': 'No evaluations recorded'}
88
+
89
+ completed = [e for e in self.evaluations if e.end_time is not None]
90
+
91
+ if not completed:
92
+ return {'error': 'No completed evaluations'}
93
+
94
+ times = [e.wall_clock_time_seconds for e in completed]
95
+ rounds = [e.total_agent_rounds for e in completed]
96
+
97
+ alignment_scores = [e.expert_alignment_score for e in completed
98
+ if e.expert_alignment_score is not None]
99
+ overall_scores = [e.overall_score for e in completed
100
+ if e.overall_score is not None]
101
+
102
+ import numpy as np
103
+
104
+ return {
105
+ 'total_evaluations': len(completed),
106
+ 'timing': {
107
+ 'mean_seconds': np.mean(times),
108
+ 'std_seconds': np.std(times),
109
+ 'min_seconds': np.min(times),
110
+ 'max_seconds': np.max(times)
111
+ },
112
+ 'agent_rounds': {
113
+ 'mean': np.mean(rounds),
114
+ 'std': np.std(rounds),
115
+ 'min': np.min(rounds),
116
+ 'max': np.max(rounds)
117
+ },
118
+ 'expert_alignment': {
119
+ 'mean': np.mean(alignment_scores) if alignment_scores else None,
120
+ 'n_rated': len(alignment_scores)
121
+ },
122
+ 'overall_scores': {
123
+ 'mean': np.mean(overall_scores) if overall_scores else None,
124
+ 'std': np.std(overall_scores) if overall_scores else None
125
+ }
126
+ }
127
+
128
+
129
+ # Ground truth for validation against literature consensus
130
+ LITERATURE_CONSENSUS = {
131
+ 'portfolio_optimization_qaoa': {
132
+ 'quantum_advantage_near_term': False,
133
+ 'feasible_on_nisq': True, # Can run, but no advantage
134
+ 'bottleneck': 'noise_and_classical_competition',
135
+ 'recommended_approach': 'hybrid',
136
+ 'references': [
137
+ 'Egger et al. (2020) - Quantum Computing for Finance',
138
+ 'Herman et al. (2022) - Portfolio Optimization Survey'
139
+ ]
140
+ },
141
+ 'option_pricing_amplitude_estimation': {
142
+ 'quantum_advantage_near_term': False,
143
+ 'feasible_on_nisq': False, # Requires error correction
144
+ 'bottleneck': 'circuit_depth_and_error_correction',
145
+ 'recommended_approach': 'classical_monte_carlo',
146
+ 'references': [
147
+ 'Stamatopoulos et al. (2020) - Option Pricing using QC',
148
+ 'Chakrabarti et al. (2021) - Threshold for Quantum Speedup'
149
+ ]
150
+ },
151
+ 'fraud_detection_quantum_ml': {
152
+ 'quantum_advantage_near_term': False,
153
+ 'feasible_on_nisq': True, # Can run, limited scale
154
+ 'bottleneck': 'data_loading_and_classical_ml_strength',
155
+ 'recommended_approach': 'classical_ml',
156
+ 'references': [
157
+ 'Schuld & Petruccione (2021) - ML with Quantum Computers',
158
+ 'Tang (2019) - Quantum-inspired classical algorithms'
159
+ ]
160
+ },
161
+ 'risk_analysis_quantum_monte_carlo': {
162
+ 'quantum_advantage_near_term': False,
163
+ 'feasible_on_nisq': False,
164
+ 'bottleneck': 'quadratic_speedup_insufficient_with_noise',
165
+ 'recommended_approach': 'gpu_accelerated_classical',
166
+ 'references': [
167
+ 'Woerner & Egger (2019) - Quantum Risk Analysis',
168
+ 'Miyamoto & Shiohara (2022) - Bermudan Option Pricing'
169
+ ]
170
+ },
171
+ 'credit_scoring_vqc': {
172
+ 'quantum_advantage_near_term': False,
173
+ 'feasible_on_nisq': True,
174
+ 'bottleneck': 'barren_plateaus_and_expressibility',
175
+ 'recommended_approach': 'classical_ensemble_methods',
176
+ 'references': [
177
+ 'McClean et al. (2018) - Barren Plateaus',
178
+ 'Cerezo et al. (2021) - Variational Quantum Algorithms'
179
+ ]
180
+ }
181
+ }
182
+
183
+
184
+ def calculate_expert_alignment(
185
+ agent_output: dict,
186
+ use_case_key: str
187
+ ) -> dict:
188
+ """
189
+ Calculate alignment between agent output and literature consensus.
190
+
191
+ Args:
192
+ agent_output: Structured output from the agent crew
193
+ use_case_key: Key into LITERATURE_CONSENSUS dict
194
+
195
+ Returns:
196
+ Alignment analysis with score
197
+ """
198
+ if use_case_key not in LITERATURE_CONSENSUS:
199
+ return {
200
+ 'error': f'Unknown use case: {use_case_key}',
201
+ 'available_cases': list(LITERATURE_CONSENSUS.keys())
202
+ }
203
+
204
+ consensus = LITERATURE_CONSENSUS[use_case_key]
205
+ alignment_checks = []
206
+
207
+ # Check quantum advantage assessment
208
+ if 'quantum_advantage' in agent_output:
209
+ agent_says_advantage = agent_output.get('quantum_advantage', False)
210
+ consensus_advantage = consensus['quantum_advantage_near_term']
211
+ alignment_checks.append({
212
+ 'criterion': 'quantum_advantage_assessment',
213
+ 'agent': agent_says_advantage,
214
+ 'consensus': consensus_advantage,
215
+ 'aligned': agent_says_advantage == consensus_advantage
216
+ })
217
+
218
+ # Check feasibility assessment
219
+ if 'feasible_on_nisq' in agent_output:
220
+ agent_feasible = agent_output.get('feasible_on_nisq', False)
221
+ consensus_feasible = consensus['feasible_on_nisq']
222
+ alignment_checks.append({
223
+ 'criterion': 'nisq_feasibility',
224
+ 'agent': agent_feasible,
225
+ 'consensus': consensus_feasible,
226
+ 'aligned': agent_feasible == consensus_feasible
227
+ })
228
+
229
+ # Calculate alignment score
230
+ if alignment_checks:
231
+ aligned_count = sum(1 for c in alignment_checks if c['aligned'])
232
+ alignment_score = aligned_count / len(alignment_checks)
233
+ else:
234
+ alignment_score = None
235
+
236
+ return {
237
+ 'use_case': use_case_key,
238
+ 'alignment_checks': alignment_checks,
239
+ 'alignment_score': alignment_score,
240
+ 'consensus_references': consensus['references']
241
+ }
242
+
243
+
244
+ def extract_scores_from_text(text: str) -> dict:
245
+ """
246
+ Extract numerical scores from agent output text.
247
+
248
+ Looks for patterns like:
249
+ - "score: 0.7"
250
+ - "feasibility score (0-1): 0.65"
251
+ - "Rating: 7/10"
252
+ """
253
+ scores = {}
254
+
255
+ # Pattern: "X score: 0.Y" or "X score (0-1): 0.Y"
256
+ score_pattern = r'(\w+(?:\s+\w+)?)\s+score\s*(?:\([^)]+\))?\s*[:=]\s*([\d.]+)'
257
+ for match in re.finditer(score_pattern, text, re.IGNORECASE):
258
+ label = match.group(1).lower().replace(' ', '_')
259
+ value = float(match.group(2))
260
+ if 0 <= value <= 1:
261
+ scores[f'{label}_score'] = value
262
+ elif 0 <= value <= 10:
263
+ scores[f'{label}_score'] = value / 10
264
+
265
+ # Pattern: "Rating: X/10"
266
+ rating_pattern = r'rating\s*[:=]\s*([\d.]+)\s*/\s*10'
267
+ for match in re.finditer(rating_pattern, text, re.IGNORECASE):
268
+ value = float(match.group(1))
269
+ scores['rating'] = value / 10
270
+
271
+ return scores
272
+
273
+
274
+ class HallucinationChecker:
275
+ """
276
+ Check agent outputs for potential hallucinations.
277
+
278
+ Compares claims against known facts about quantum computing
279
+ and finance applications.
280
+ """
281
+
282
+ # Known facts for validation
283
+ KNOWN_FACTS = {
284
+ # Hardware facts (2024-2026)
285
+ 'ibm_qubit_count': (433, 1121), # Range: Osprey to Condor
286
+ 'ionq_qubit_count': (32, 36),
287
+ 'google_qubit_count': (72, 100),
288
+
289
+ # Algorithm facts
290
+ 'grover_speedup': 'quadratic', # sqrt(N)
291
+ 'shor_speedup': 'exponential',
292
+ 'qaoa_proven_advantage': False,
293
+ 'vqe_proven_advantage': False,
294
+
295
+ # Finance facts
296
+ 'hft_latency_requirement_us': 1, # microseconds
297
+ 'typical_portfolio_size': (10, 10000),
298
+ }
299
+
300
+ HALLUCINATION_PATTERNS = [
301
+ # Claims of proven quantum advantage for NISQ
302
+ r'proven\s+quantum\s+advantage\s+(?:for|in|on)\s+(?:NISQ|near-term)',
303
+ r'demonstrat(?:ed|es)\s+quantum\s+supremacy\s+(?:for|in)\s+finance',
304
+
305
+ # Unrealistic hardware claims
306
+ r'(?:current|available)\s+(?:quantum\s+)?computers?\s+(?:with|have)\s+(?:\d{4,}|\d+,\d{3,})\s+qubits',
307
+
308
+ # Impossible speedup claims
309
+ r'exponential\s+speedup\s+(?:for|in|using)\s+(?:QAOA|VQE)',
310
+ ]
311
+
312
+ def check_output(self, text: str) -> dict:
313
+ """
314
+ Check text for potential hallucinations.
315
+
316
+ Args:
317
+ text: Agent output text to check
318
+
319
+ Returns:
320
+ Dictionary with hallucination analysis
321
+ """
322
+ findings = []
323
+
324
+ # Check against hallucination patterns
325
+ for pattern in self.HALLUCINATION_PATTERNS:
326
+ matches = re.findall(pattern, text, re.IGNORECASE)
327
+ if matches:
328
+ findings.append({
329
+ 'type': 'suspicious_claim',
330
+ 'pattern': pattern,
331
+ 'matches': matches
332
+ })
333
+
334
+ # Check qubit count claims
335
+ qubit_claims = re.findall(r'(\d+)\s*qubits?', text, re.IGNORECASE)
336
+ for claim in qubit_claims:
337
+ count = int(claim)
338
+ if count > 2000: # No current hardware has this many
339
+ findings.append({
340
+ 'type': 'unrealistic_qubit_count',
341
+ 'claimed': count,
342
+ 'realistic_max': 1121
343
+ })
344
+
345
+ return {
346
+ 'potential_hallucinations': len(findings),
347
+ 'findings': findings,
348
+ 'text_length': len(text)
349
+ }
350
+
351
+
352
+ if __name__ == "__main__":
353
+ # Demo metrics collection
354
+ collector = MetricsCollector()
355
+
356
+ # Simulate an evaluation
357
+ metrics = collector.start_evaluation(
358
+ "Quantum portfolio optimization using QAOA"
359
+ )
360
+ metrics.total_agent_rounds = 5
361
+ metrics.quantum_feasibility_score = 0.6
362
+ metrics.hardware_readiness_score = 0.4
363
+ metrics.classical_competitiveness_score = 0.8
364
+ metrics.business_viability_score = 0.5
365
+ metrics.overall_score = 0.3
366
+ metrics.expert_alignment_score = 0.85
367
+
368
+ import time
369
+ time.sleep(0.1) # Simulate some work
370
+ metrics.complete()
371
+
372
+ print("Evaluation Metrics Demo")
373
+ print("=" * 50)
374
+ print(metrics.to_dict())
375
+
376
+ print("\nSummary Statistics:")
377
+ print(collector.get_summary_statistics())