/
dimaWebexplorer
/
investmentAssistant
Обзор
Документация
Войти
/
dimaWebexplorer
/
investmentAssistant
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
llmcode
backend/main.py
146 строк
7 KB
yyeewweee
update backend/main.py
17 дек 2025, 19:49
17 дек 2025, 19:49
a5eee66
Код
Авторство
О чём код?
from backend.module import (parse_moex_stocks, parse_moex_bonds, get_stocks_above_yield, get_bonds_by_yield, calculate_regular_deposit_accumulation, calculate_regular_deposit_passive, create_portfolio, post_news_sentiment_endpoint) from ml.reasoning import (integrate_openrouter_reasoning_stocks) from fastapi import FastAPI from pydantic import BaseModel from fastapi.middleware.cors import CORSMiddleware import os from pathlib import Path from dotenv import load_dotenv BASE_DIR = Path(__file__).resolve().parent ENV_FILE_PATH = BASE_DIR / ".env" load_dotenv(dotenv_path=ENV_FILE_PATH) app = FastAPI() origins = [ "http://localhost:5173", "https://yourdomain.com", "*", ] app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) class RequestData(BaseModel): target_yield: float task: str future_value: float years: int want_to_get: float stock_bond_ratio: float class PortfolioNewsSentimentRequestData(BaseModel): portfolio_list: list # Список словарей, полученный из /portfolio finbert_model_name: str = "ProsusAI/finbert" @app.post("/portfolio") async def calculate(data: RequestData): #1) Функции парсинга ценных бумаг df_stocks = parse_moex_stocks() df_bonds = parse_moex_bonds() #2) Функции фильтрации ценных бумаг по критерию доходности result_df_stocks = get_stocks_above_yield(data.target_yield, df_stocks) result_df_bonds = get_bonds_by_yield(data.target_yield, df_bonds) #3) Функции расчета суммы внесения на депозит в зависимости от задачи if data.task == "accumulation": regular_deposit = calculate_regular_deposit_accumulation(data.future_value, data.target_yield, data.years) elif data.task == "passive": regular_deposit = calculate_regular_deposit_passive(data.want_to_get, data.target_yield, data.years) #4) Функция создания портфеля portfolio = create_portfolio( regular_deposit=regular_deposit, result_df_stocks=result_df_stocks, result_df_bonds=result_df_bonds, stock_bond_ratio=data.stock_bond_ratio) portfolio_list = portfolio.to_dict('records') return {"portfolio": portfolio_list} @app.post("/news_sentiment") async def get_news_sentiment(news_data: PortfolioNewsSentimentRequestData): tavily_api_key_str = os.getenv("TAVILY_API_KEY") if not tavily_api_key_str: # Попробуем вывести отладочную информацию print(f"DEBUG: TAVILY_API_KEY is None or empty. Looking in: {ENV_FILE_PATH}") print(f"DEBUG: File {ENV_FILE_PATH} exists: {ENV_FILE_PATH.exists()}") if ENV_FILE_PATH.exists(): print("Contents of .env file:") try: with ENV_FILE_PATH.open('r', encoding='utf-8') as f: print(f.read()) except Exception as e: print(f"Could not read file: {e}") return {"error": "TAVILY_API_KEY не найден в переменных окружения. Проверьте файл .env."} portfolio_list = news_data.portfolio_list finbert_model_name = news_data.finbert_model_name news_sentiment_df = post_news_sentiment_endpoint( first_method_output_df_or_list=portfolio_list, tavily_api_key_str=tavily_api_key_str, finbert_model_name_or_path=finbert_model_name ) news_sentiment_list = news_sentiment_df.to_dict('records') return {"news_sentiment": news_sentiment_list} @app.post("/portfolio_ml") async def ml_calculate(data: RequestData): # 1) Функции парсинга ценных бумаг df_stocks = parse_moex_stocks() df_bonds = parse_moex_bonds() # Убрали # 2) Функции фильтрации ценных бумаг по критерию доходности result_df_stocks = get_stocks_above_yield(data.target_yield, df_stocks) result_df_bonds = get_bonds_by_yield(data.target_yield, df_bonds) # Убрали # --- Интеграция рассуждений OpenRouter для акций --- # Проверим, есть ли подходящие акции refined_stock_positions = pd.DataFrame() # Инициализируем пустой DataFrame if not result_df_stocks.empty: # Пример промпта для модели, можно передавать из RequestData user_stock_prompt = f""" Выбери акции, которые наилучшим образом соответствуют следующим критериям: - Дивидендная доходность не ниже {data.target_yield * 100:.2f}% годовых. - Приоритет у акций крупных, надежных эмитентов. - Избегай слишком мелких эмитентов и бумаг с низкой ликвидностью (если есть данные о ликвидности). - Учитывай соотношение цена/доходность. """ # Интегрируем рассуждение модели refined_stock_positions = integrate_openrouter_reasoning_stocks(result_df_stocks, user_stock_prompt) # Теперь refined_stock_positions содержит уточненный список акций с рассчитанным количеством # 3) Функции расчета суммы внесения на депозит в зависимости от задачи if data.task == "accumulation": regular_deposit = calculate_regular_deposit_accumulation(data.future_value, data.target_yield, data.years) elif data.task == "passive": regular_deposit = calculate_regular_deposit_passive(data.want_to_get, data.target_yield, data.years) # 4) Функция создания портфеля с использованием уточненных списков # Если у нас есть уточненные позиции от модели, используем их, иначе используем оригинальные расчеты portfolio = create_portfolio( regular_deposit=regular_deposit, result_df_stocks=refined_stock_positions, result_df_bonds=result_df_bonds, stock_bond_ratio=data.stock_bond_ratio) portfolio_list = portfolio.to_dict('records') return {"portfolio": portfolio_list}