SPB Git

spb/vquant Public MIT

VibeQuant — AI-powered institutional-grade financial intelligence platform.

TypeScript 84.3% Python 11.7% JavaScript 1.6% CSS 1.5% HTML 0.7%
6.4 KB · 166 lines python
Raw Blame History
1#!/usr/bin/env python32# =============================================================================3#  VibeQuant (vquant) — AI-Powered Financial Intelligence Platform4# -----------------------------------------------------------------------------5#  File:      server/services/monteCarloService.py6#7#  Author:    Simon-Pierre Boucher8#  Contact:   contact@spboucher.ai9#  Website:   https://www.spboucher.ai10#  Demo:      https://www.vquant.ai11#  License:   MIT (see LICENSE)12#13#  Copyright © 2026 Simon-Pierre Boucher. All rights reserved.14# =============================================================================1516"""17Monte Carlo Simulation Service18Executes Monte Carlo simulations using financial data from FMP API directly19"""20import json21import sys22import numpy as np23from scipy import stats24import pandas as pd25import os2627# Import our FMP client28sys.path.insert(0, os.path.dirname(__file__))29from fmpClient import get_historical_prices3031def run_monte_carlo_simulation(data_json: str) -> dict:32    """33    Run Monte Carlo simulation based on provided financial data3435    Args:36        data_json: JSON string containing EITHER:37            Option 1 (Direct API mode - RECOMMENDED):38                - symbol: Stock ticker symbol (e.g., 'AAPL')39                - num_simulations: Number of Monte Carlo simulations to run40                - time_horizon: Number of days to project41                - initial_investment: Starting investment amount4243            Option 2 (Manual data mode):44                - historical_prices: List of historical prices45                - num_simulations: Number of Monte Carlo simulations to run46                - time_horizon: Number of days to project47                - initial_investment: Starting investment amount4849    Returns:50        Dictionary containing simulation results and statistics51    """52    try:53        data = json.loads(data_json)5455        # Check if symbol is provided (new API mode)56        symbol = data.get('symbol')57        if symbol:58            # Fetch historical prices directly from FMP API59            print(f"Fetching historical prices for {symbol} from FMP API...", file=sys.stderr)60            hist_data = get_historical_prices(symbol)6162            # Extract closing prices (most recent first, so reverse for chronological order)63            historical_prices = np.array([h['close'] for h in reversed(hist_data['historical'])])64            print(f"Fetched {len(historical_prices)} historical prices for {symbol}", file=sys.stderr)65        else:66            # Use provided historical prices (old mode)67            historical_prices = np.array(data.get('historical_prices', []))6869        # Extract parameters70        num_simulations = data.get('num_simulations', 10000)71        time_horizon = data.get('time_horizon', 252)  # Default 1 year trading days72        initial_investment = data.get('initial_investment', 10000)73        74        if len(historical_prices) < 2:75            return {76                "error": "Need at least 2 historical prices for simulation",77                "success": False78            }79        80        # Calculate daily returns81        returns = np.diff(historical_prices) / historical_prices[:-1]82        83        # Calculate mean and standard deviation of returns84        mean_return = np.mean(returns)85        std_return = np.std(returns)86        87        # Run Monte Carlo simulations88        simulation_results = np.zeros((num_simulations, time_horizon))89        final_values = np.zeros(num_simulations)90        91        for i in range(num_simulations):92            # Generate random returns based on historical distribution93            daily_returns = np.random.normal(mean_return, std_return, time_horizon)94            95            # Calculate price path96            price_path = initial_investment * np.cumprod(1 + daily_returns)97            simulation_results[i] = price_path98            final_values[i] = price_path[-1]99        100        # Calculate statistics101        mean_final_value = np.mean(final_values)102        median_final_value = np.median(final_values)103        std_final_value = np.std(final_values)104        min_final_value = np.min(final_values)105        max_final_value = np.max(final_values)106        107        # Calculate percentiles108        percentile_5 = np.percentile(final_values, 5)109        percentile_25 = np.percentile(final_values, 25)110        percentile_75 = np.percentile(final_values, 75)111        percentile_95 = np.percentile(final_values, 95)112        113        # Calculate probability of profit114        prob_profit = np.sum(final_values > initial_investment) / num_simulations * 100115        116        # Get sample paths for visualization (10 random simulations)117        sample_indices = np.random.choice(num_simulations, min(10, num_simulations), replace=False)118        sample_paths = simulation_results[sample_indices].tolist()119        120        # Return results121        results = {122            "success": True,123            "parameters": {124                "num_simulations": num_simulations,125                "time_horizon": time_horizon,126                "initial_investment": initial_investment,127                "mean_return": float(mean_return),128                "std_return": float(std_return)129            },130            "statistics": {131                "mean_final_value": float(mean_final_value),132                "median_final_value": float(median_final_value),133                "std_final_value": float(std_final_value),134                "min_final_value": float(min_final_value),135                "max_final_value": float(max_final_value),136                "percentile_5": float(percentile_5),137                "percentile_25": float(percentile_25),138                "percentile_75": float(percentile_75),139                "percentile_95": float(percentile_95),140                "probability_of_profit": float(prob_profit)141            },142            "sample_paths": sample_paths,143            "final_values_distribution": {144                "bins": np.histogram(final_values, bins=50)[1].tolist(),145                "counts": np.histogram(final_values, bins=50)[0].tolist()146            }147        }148        149        return results150        151    except Exception as e:152        return {153            "error": str(e),154            "success": False155        }156157if __name__ == "__main__":158    # Read input from stdin159    input_data = sys.stdin.read()160    161    # Run simulation162    result = run_monte_carlo_simulation(input_data)163    164    # Output result as JSON165    print(json.dumps(result))166