File size: 3,082 Bytes
3e49315
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import multiprocessing

import random
import math


def complex_stock_valuation(stock):
    # Basic value
    base_value = stock['price'] * stock['quantity']
    
    # Simulate a more complex valuation model
    pe_ratio = random.uniform(10, 30)
    beta = random.uniform(0.5, 2.0)
    risk_free_rate = 0.02  # 2% risk-free rate
    market_return = 0.08  # 8% market return
    
    # Calculate expected return using CAPM (Capital Asset Pricing Model)
    expected_return = risk_free_rate + beta * (market_return - risk_free_rate)
    
    # Calculate dividend yield
    dividend_yield = random.uniform(0.01, 0.05)
    
    # Dividend Discount Model
    growth_rate = random.uniform(0.02, 0.10)
    intrinsic_value = (stock['price'] * dividend_yield * (1 + growth_rate)) / (expected_return - growth_rate)
    
    # Adjust value based on a weighted average of different factors
    adjusted_value = (
        base_value * 0.4 +  # 40% weight to market value
        intrinsic_value * 0.3 +  # 30% weight to intrinsic value
        (base_value / pe_ratio) * 0.2 +  # 20% weight to earnings-based value
        (base_value * (1 + expected_return)) * 0.1  # 10% weight to expected future value
    )
    
    # Add some non-linear complexity
    volatility = random.uniform(0.1, 0.5)
    adjusted_value *= math.exp(-volatility * beta)
    
    # Simulate some intensive calculation
    for _ in range(1000):
        adjusted_value = math.sqrt((adjusted_value ** 2 + base_value ** 2) / 2)
    
    return adjusted_value

def calculate_value(portfolio_slice, queue):
    total_value = 0
    for stock in portfolio_slice:
        total_value += complex_stock_valuation(stock)
    queue.put(total_value)  # Send the result back to the main process

def parallel_portfolio_valuation(portfolio, num_processes=2):
    portfolio_size = len(portfolio)
    num_processes = min(num_processes, portfolio_size)  # Ensure num_processes doesn't exceed portfolio_size
    chunk_size = max(1, portfolio_size // num_processes)
    processes = []
    queue = multiprocessing.Queue()  # Queue for collecting results
    chunks_processed = 0  # Keep track of how many chunks we've processed

    for i in range(num_processes):
        start_index = i * chunk_size
        end_index = min((i + 1) * chunk_size, portfolio_size)
        portfolio_slice = portfolio[start_index:end_index]
        if portfolio_slice:  # Only start a process if there are items to process
            process = multiprocessing.Process(target=calculate_value, args=(portfolio_slice, queue))
            processes.append(process)
            process.start()
            chunks_processed += 1  # Increment for each chunk we process

    total_value = 0
    # Collect results for each chunk we processed
    for _ in range(chunks_processed):
        total_value += queue.get()

    # Wait for all processes to finish
    for process in processes:
        process.join()

    return total_value



def serialCal(portfolio):
    total = 0
    for stock in portfolio:
        total += complex_stock_valuation(stock)
    return total