Загрузка данных


# -*- coding: utf-8 -*-
# modules/forecasting.py

import numpy as np

def monte_carlo_forecast(pool_values, pool_weights=None, num_simulations=100000, p1=0.05, p2=0.95):
    """
    Выполняет симуляцию методом Монте-Карло с учетом весов.
    :param pool_values: Список значений показателей (пул).
    :param pool_weights: Список весов для каждого показателя. Если None, используется равновероятный выбор.
    :param num_simulations: Количество итераций симуляции.
    :param p1: Нижняя граница квантиля (например, 0.05).
    :param p2: Верхняя граница квантиля (например, 0.95).
    :return: Словарь с результатами.
    """
    if not pool_values:
        raise ValueError("Пул значений для симуляции пуст.")

    # Если веса не заданы, создаем массив из единиц (равновероятный выбор)
    if pool_weights is None:
        probabilities = None
    else:
        # Важно: веса должны быть приведены к вероятностям (сумма = 1)
        total_weight = sum(pool_weights)
        probabilities = np.array(pool_weights) / total_weight

    results = []
    n = len(pool_values)

    for _ in range(num_simulations):
        # Выбираем k - размер подмножества. Для простоты возьмем случайное от 1 до n
        k = np.random.randint(1, n + 1)
        # Выбираем k элементов из пула с учетом весов
        sample = np.random.choice(pool_values, size=k, p=probabilities)
        results.append(np.sum(sample))

    if not results:
        return {"error": "Не удалось получить результаты симуляции."}

    results_array = np.array(results)
    
    return {
        "lower_bound": float(np.percentile(results_array, p1 * 100)),
        "upper_bound": float(np.percentile(results_array, p2 * 100)),
        "median": float(np.median(results_array)),
        "simulations": results_array.tolist()
    }