Coverage for src/ifunnel/models/MVOtargets.py: 100%

30 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-07-12 09:14 +0000

1import numpy as np 

2import pandas as pd 

3from loguru import logger 

4 

5from .ScenarioGeneration import MomentGenerator 

6 

7 

8# FUNCTION RUNNING THE OPTIMIZATION 

9# ---------------------------------------------------------------------- 

10def portfolio_risk_target(covariance: np.array) -> float: 

11 # Fixed equal weight x 

12 n = covariance.shape[0] 

13 x = np.ones(n) / n 

14 

15 # Volatility 

16 portfolio_vty = np.sqrt(x @ covariance @ x) 

17 

18 return portfolio_vty 

19 

20 

21# ---------------------------------------------------------------------- 

22# Mathematical Optimization: TARGETS GENERATION 

23# ---------------------------------------------------------------------- 

24def get_mvo_targets( 

25 test_date: str, benchmark: list, budget: int, data: pd.DataFrame 

26) -> tuple[pd.DataFrame, pd.DataFrame]: 

27 logger.info(f"🎯 Generating Volatility targets for {benchmark}") 

28 

29 # Define Benchmark 

30 tickers = benchmark 

31 # Get weekly return of our benchmark 

32 whole_dataset_benchmark = data[tickers].copy() 

33 

34 # Get weekly data just for testing period 

35 test_dataset_benchmark = whole_dataset_benchmark[whole_dataset_benchmark.index >= test_date] 

36 

37 # Number of weeks for testing 

38 weeks_n = len(test_dataset_benchmark.index) 

39 

40 # Get parameters 

41 sigma_lst, _ = MomentGenerator.generate_sigma_mu_for_test_periods(whole_dataset_benchmark, weeks_n) 

42 

43 # Compute the optimal portfolio outperforming zero percentage return 

44 # ---------------------------------------------------------------------- 

45 p_points = len(sigma_lst) # number of periods 

46 

47 # COMPUTE MVO TARGETS 

48 list_targets = [] 

49 for p in range(p_points): 

50 # Get parameters for a given period p 

51 sigma = sigma_lst[p] 

52 

53 # Compute volatility targets 

54 vty_target = portfolio_risk_target(sigma) 

55 

56 # save the result 

57 list_targets.append(vty_target) 

58 

59 # Generate new column so that dtype is set right. 

60 targets = pd.DataFrame(columns=["Vty_Target"], data=list_targets) 

61 

62 # COMPUTE PORTFOLIO VALUE 

63 list_portfolio_values = [] 

64 for w in test_dataset_benchmark.index: 

65 budget_next = sum((budget / len(tickers)) * (1 + test_dataset_benchmark.loc[w, :])) 

66 list_portfolio_values.append(budget_next) 

67 budget = budget_next 

68 

69 # Generate dataframe so that dtype is set right. 

70 portfolio_value = pd.DataFrame( 

71 columns=["Benchmark_Value"], 

72 index=test_dataset_benchmark.index, 

73 data=list_portfolio_values, 

74 ) 

75 

76 return targets, portfolio_value