File size: 6,947 Bytes
96e7d53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import json
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pickle
# Function for Monte Carlo Simulation
def monte_carlo_simulation(portfolio_data, scenario_data, num_simulations=10000):
    """

    Performs a Monte Carlo simulation on a portfolio based on market scenarios.



    Args:

        portfolio_data (dict): Dictionary of portfolio data.

        scenario_data (dict): Dictionary of market scenario data.

        num_simulations (int, optional): The number of simulations. Defaults to 10000.



    Returns:

        dict: A dictionary containing simulation results for each scenario.

    """
    scenarios = scenario_data["market_scenarios"]
    results = {}

    for scenario_key, scenario_details in scenarios.items():
        scenario_name = scenario_details["name"]
        sector_impacts = scenario_details.get("sector_impact", {})
        results[scenario_name] = {
            "portfolio_values": [],
            "average_return": 0,
            "std_dev_return": 0,
            "percentiles": {},
        }

        for _ in range(num_simulations):
            portfolio_value = 0
            for asset_name, asset_details in portfolio_data["assets"].items():
                sector = asset_details["sector"]
                quantity = asset_details["quantity"]
                initial_price = asset_details["initial_price"]

                price_change_percentage = 0
                if sector in sector_impacts:
                    price_change_percentage = np.random.normal(
                        loc=sector_impacts[sector] / 100, scale=0.1
                    )

                # Calculate the new price
                new_price = initial_price * (1 + price_change_percentage)

                portfolio_value += new_price * quantity
            results[scenario_name]["portfolio_values"].append(portfolio_value)

        # Calculate Results
        portfolio_values = results[scenario_name]["portfolio_values"]
        initial_portfolio_value = sum(
            asset["quantity"] * asset["initial_price"] for asset in portfolio_data["assets"].values()
        )
        returns = [
            (value - initial_portfolio_value) / initial_portfolio_value
            for value in portfolio_values
        ]

        results[scenario_name]["average_return"] = np.mean(returns)
        results[scenario_name]["std_dev_return"] = np.std(returns)
        results[scenario_name]["percentiles"] = {
            5: np.percentile(returns, 5),
            25: np.percentile(returns, 25),
            50: np.percentile(returns, 50),
            75: np.percentile(returns, 75),
            95: np.percentile(returns, 95),
        }

    return results

if __name__ == "__main__":
    # Load input data
    with open("output_files/scenario.json") as f:
        scenario_data = json.load(f)

    with open("output_files/portfolio.json") as f:
        portfolio_data = json.load(f)


    # Load the dictionary from the local file
    def load_dataframes(filename="output_files/saved_dataframes.pkl"):
        try:
            with open(filename, 'rb') as file:
                saved_dataframes = pickle.load(file)
                print(f"DataFrames successfully loaded from {filename}.")
                return saved_dataframes
        except FileNotFoundError:
            print(f"File {filename} not found.")
            return None

    saved_dataframes = load_dataframes()

    # Placeholder for storing results
    scenario_results = {}

    # Process each scenario
    for scenario_name, scenario_details in scenario_data["market_scenarios"].items():
        impacted_sectors = scenario_details["sector_impact"]

        # Filter assets in the impacted sectors
        relevant_assets = [
            symbol
            for symbol, details in portfolio_data["assets"].items()
            if details["sector"] in impacted_sectors
        ]

        # Calculate magnitudes for the scenario
        sector_magnitudes = {}
        for symbol in relevant_assets:
            df = saved_dataframes[symbol]
            sector = portfolio_data["assets"][symbol]["sector"]

            # Calculate magnitude as the absolute difference between first and last Close price
            magnitude = abs(df["Close"].iloc[-2] - df["Close"].iloc[-1])

            # Aggregate by sector
            if sector not in sector_magnitudes:
                sector_magnitudes[sector] = 0
            sector_magnitudes[sector] += magnitude

        # Calculate aggregated magnitude for the scenario
        aggregated_magnitude = sum(sector_magnitudes.values())

        # Store results
        scenario_results[scenario_name] = {
            "individual_magnitudes": sector_magnitudes,
            "aggregated_magnitude": aggregated_magnitude,
        }

    # Display results
    for scenario_name, results in scenario_results.items():
        print(f"\nScenario: {scenario_name}")
        print("Individual Sector Magnitudes:")
        for sector, magnitude in results["individual_magnitudes"].items():
            print(f"  {sector}: {magnitude:.2f}")
        print(f"Aggregated Magnitude: {results['aggregated_magnitude']:.2f}")

    # Integrate calculated results into scenario data
    for scenario_id, results in scenario_results.items():
        # Update the sector impacts to include individual magnitudes
        scenario_data["market_scenarios"][scenario_id]["sector_impact"] = results["individual_magnitudes"]
        # Update aggregated magnitude
        scenario_data["market_scenarios"][scenario_id]["aggregated_magnitude"] = results["aggregated_magnitude"]

    # Save the updated scenario data to a local JSON file
    output_file_path = "output_files/updated_scenario_data.json"
    with open(output_file_path, "w") as file:
        json.dump(scenario_data, file, indent=4)

    print(f"Updated scenario data saved to '{output_file_path}' successfully!")

    # Run Monte Carlo simulation
    simulation_results = monte_carlo_simulation(portfolio_data, scenario_data)

    # Save simulation results to a local JSON file
    simulation_results_file = "output_files/simulation_results.json"
    with open(simulation_results_file, "w") as file:
        json.dump(simulation_results, file, indent=4)

    print(f"Simulation results saved to '{simulation_results_file}' successfully!")

    # Print simulation results
    for scenario_name, results in simulation_results.items():
        print(f"Scenario: {scenario_name}")
        print(f"  Average Return: {results['average_return']:.4f}")
        print(f"  Std Dev Return: {results['std_dev_return']:.4f}")
        print("  Return Percentiles:")
        for percentile, value in results["percentiles"].items():
            print(f"    {percentile}th: {value:.4f}")
        print("-" * 40)