Spaces:
Sleeping
Sleeping
QAway-to
commited on
Commit
·
06e5903
1
Parent(s):
b50d186
model change
Browse files- analyzer.py +28 -26
- app.py +1 -1
- comparer.py +3 -3
- fetch.py +30 -21
- requirements.txt +1 -0
analyzer.py
CHANGED
|
@@ -1,38 +1,40 @@
|
|
| 1 |
-
|
| 2 |
-
import requests
|
| 3 |
-
from fetch import extract_portfolio_id
|
| 4 |
from prompts import ONE_PROMPT
|
|
|
|
| 5 |
from openai import OpenAI
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
-
|
|
|
|
| 8 |
portfolio_id = extract_portfolio_id(text)
|
| 9 |
if not portfolio_id:
|
| 10 |
yield "❗ Укажите корректный portfolioId или ссылку."
|
| 11 |
return
|
| 12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
try:
|
| 14 |
-
# Получение JSON по API
|
| 15 |
-
url = f"https://api.tradelink.pro/portfolio/get?portfolioId={portfolio_id}&extended=1"
|
| 16 |
-
response = requests.get(url)
|
| 17 |
-
json_data = response.json()
|
| 18 |
-
extended = json_data.get("data", {}).get("extended", {})
|
| 19 |
-
|
| 20 |
-
if not extended:
|
| 21 |
-
yield "❗ Метрики не найдены в ответе API."
|
| 22 |
-
return
|
| 23 |
-
|
| 24 |
-
# Передаём все числовые метрики, без фильтрации
|
| 25 |
-
metrics = {k: v for k, v in extended.items() if isinstance(v, (int, float))}
|
| 26 |
-
if not metrics:
|
| 27 |
-
yield "❗ Нет числовых метрик для анализа."
|
| 28 |
-
return
|
| 29 |
-
|
| 30 |
-
metrics_text = ", ".join([f"{k}: {v}" for k, v in metrics.items()])
|
| 31 |
-
prompt = f"Вот метрики портфеля: {metrics_text}. Проанализируй их. Дай общий отчёт на русском языке"
|
| 32 |
-
|
| 33 |
-
# Запрос к модели
|
| 34 |
response_llm = client.chat.completions.create(
|
| 35 |
-
# model="nasiruddin15/Mistral-dolphin-2.8-grok-instract-2-7B-slerp",
|
| 36 |
model="meta-llama/Meta-Llama-3.1-8B-Instruct",
|
| 37 |
messages=[
|
| 38 |
{"role": "system", "content": ONE_PROMPT},
|
|
@@ -49,4 +51,4 @@ def analyze_portfolio_streaming(text: str, client:OpenAI):
|
|
| 49 |
yield partial
|
| 50 |
|
| 51 |
except Exception as e:
|
| 52 |
-
yield f"❌ Ошибка при
|
|
|
|
| 1 |
+
import httpx
|
|
|
|
|
|
|
| 2 |
from prompts import ONE_PROMPT
|
| 3 |
+
from fetch import extract_portfolio_id
|
| 4 |
from openai import OpenAI
|
| 5 |
+
import asyncio
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
async def get_portfolio_metrics(portfolio_id: str) -> dict | None:
|
| 9 |
+
url = f"https://api.tradelink.pro/portfolio/get?portfolioId={portfolio_id}&extended=1"
|
| 10 |
+
try:
|
| 11 |
+
async with httpx.AsyncClient(timeout=10) as client:
|
| 12 |
+
response = await client.get(url)
|
| 13 |
+
data = response.json().get("data", {}).get("extended", {})
|
| 14 |
+
return {k: v for k, v in data.items() if isinstance(v, (int, float))}
|
| 15 |
+
except Exception as e:
|
| 16 |
+
print(f"[API Error]: {e}")
|
| 17 |
+
return None
|
| 18 |
|
| 19 |
+
|
| 20 |
+
def analyze_portfolio_streaming(text: str, client: OpenAI):
|
| 21 |
portfolio_id = extract_portfolio_id(text)
|
| 22 |
if not portfolio_id:
|
| 23 |
yield "❗ Укажите корректный portfolioId или ссылку."
|
| 24 |
return
|
| 25 |
|
| 26 |
+
yield "⏳ Загружаю метрики портфеля..."
|
| 27 |
+
|
| 28 |
+
metrics = asyncio.run(get_portfolio_metrics(portfolio_id))
|
| 29 |
+
if not metrics:
|
| 30 |
+
yield "❗ Не удалось получить метрики портфеля."
|
| 31 |
+
return
|
| 32 |
+
|
| 33 |
+
metrics_text = ", ".join([f"{k}: {v}" for k, v in metrics.items()])
|
| 34 |
+
prompt = f"Вот метрики портфеля: {metrics_text}. Проанализируй их. Дай общий отчёт на русском языке."
|
| 35 |
+
|
| 36 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
response_llm = client.chat.completions.create(
|
|
|
|
| 38 |
model="meta-llama/Meta-Llama-3.1-8B-Instruct",
|
| 39 |
messages=[
|
| 40 |
{"role": "system", "content": ONE_PROMPT},
|
|
|
|
| 51 |
yield partial
|
| 52 |
|
| 53 |
except Exception as e:
|
| 54 |
+
yield f"❌ Ошибка при генерации ответа: {e}"
|
app.py
CHANGED
|
@@ -2,7 +2,7 @@ import gradio as gr
|
|
| 2 |
import os
|
| 3 |
from prompts import TRADELINK_CONTEXT
|
| 4 |
from fetch import extract_portfolio_id
|
| 5 |
-
from fetch import
|
| 6 |
from openai import OpenAI
|
| 7 |
from analyzer import analyze_portfolio_streaming
|
| 8 |
from comparer import compare_portfolio
|
|
|
|
| 2 |
import os
|
| 3 |
from prompts import TRADELINK_CONTEXT
|
| 4 |
from fetch import extract_portfolio_id
|
| 5 |
+
from fetch import fetch_metrics_async
|
| 6 |
from openai import OpenAI
|
| 7 |
from analyzer import analyze_portfolio_streaming
|
| 8 |
from comparer import compare_portfolio
|
comparer.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
|
| 2 |
from fetch import extract_portfolio_id
|
| 3 |
-
from fetch import
|
| 4 |
from prompts import COMPARE_PROMPT
|
| 5 |
from openai import OpenAI
|
| 6 |
|
|
@@ -15,8 +15,8 @@ def compare_portfolio(text1: str, text2: str, client: OpenAI):
|
|
| 15 |
yield "❗ Один или оба portfolioId некорректны."
|
| 16 |
return
|
| 17 |
|
| 18 |
-
m1 =
|
| 19 |
-
m2 =
|
| 20 |
if not m1 or not m2:
|
| 21 |
yield "❗ Не удалось получить метрики одного из портфелей."
|
| 22 |
return
|
|
|
|
| 1 |
|
| 2 |
from fetch import extract_portfolio_id
|
| 3 |
+
from fetch import fetch_metrics_async
|
| 4 |
from prompts import COMPARE_PROMPT
|
| 5 |
from openai import OpenAI
|
| 6 |
|
|
|
|
| 15 |
yield "❗ Один или оба portfolioId некорректны."
|
| 16 |
return
|
| 17 |
|
| 18 |
+
m1 = fetch_metrics_async(id1)
|
| 19 |
+
m2 = fetch_metrics_async(id2)
|
| 20 |
if not m1 or not m2:
|
| 21 |
yield "❗ Не удалось получить метрики одного из портфелей."
|
| 22 |
return
|
fetch.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
import re
|
| 2 |
import requests
|
|
|
|
| 3 |
|
| 4 |
#Извлечение UUID из строки
|
| 5 |
def extract_portfolio_id(text: str) -> str | None:
|
|
@@ -9,28 +10,36 @@ def extract_portfolio_id(text: str) -> str | None:
|
|
| 9 |
)
|
| 10 |
return match.group(0) if match else None
|
| 11 |
|
| 12 |
-
def
|
|
|
|
| 13 |
try:
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
"kSortino", "kCalmar", "kSharpe",
|
| 22 |
-
|
| 23 |
-
# 🔹 Просадки
|
| 24 |
-
"maxDD", "mddDuration", "maxBalance",
|
| 25 |
-
|
| 26 |
-
# 🔹 Поведение стратегии
|
| 27 |
-
"losingDays", "winningDays", "selfProfitRate",
|
| 28 |
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
-
|
| 34 |
-
except:
|
| 35 |
-
|
| 36 |
|
|
|
|
| 1 |
import re
|
| 2 |
import requests
|
| 3 |
+
import httpx
|
| 4 |
|
| 5 |
#Извлечение UUID из строки
|
| 6 |
def extract_portfolio_id(text: str) -> str | None:
|
|
|
|
| 10 |
)
|
| 11 |
return match.group(0) if match else None
|
| 12 |
|
| 13 |
+
async def fetch_metrics_async(portfolio_id: str) -> dict | None:
|
| 14 |
+
url = f"https://api.tradelink.pro/portfolio/get?portfolioId={portfolio_id}&extended=1"
|
| 15 |
try:
|
| 16 |
+
async with httpx.AsyncClient(timeout=10) as client:
|
| 17 |
+
resp = await client.get(url)
|
| 18 |
+
extended = resp.json().get("data", {}).get("extended", {})
|
| 19 |
+
return {k: v for k, v in extended.items() if isinstance(v, (int, float))}
|
| 20 |
+
except Exception as e:
|
| 21 |
+
print(f"[API ошибка]: {e}")
|
| 22 |
+
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
+
# print(f"[API ошибка]: {e}")
|
| 25 |
+
# return None
|
| 26 |
+
#
|
| 27 |
+
# keys = [
|
| 28 |
+
# # 🔹 Доходность и риск
|
| 29 |
+
# "alphaRatio", "betaRatio", "cagr", "sharpe", "sortino", "volatility",
|
| 30 |
+
# "kSortino", "kCalmar", "kSharpe",
|
| 31 |
+
#
|
| 32 |
+
# # 🔹 Просадки
|
| 33 |
+
# "maxDD", "mddDuration", "maxBalance",
|
| 34 |
+
#
|
| 35 |
+
# # 🔹 Поведение стратегии
|
| 36 |
+
# "losingDays", "winningDays", "selfProfitRate",
|
| 37 |
+
#
|
| 38 |
+
# # 🔹 Актуальные показатели доходности
|
| 39 |
+
# "lastWeekNetProfit", "lastMonthNetProfit", "lastQuarterGrowth", "lastYearNetGrowth"
|
| 40 |
+
# ]
|
| 41 |
|
| 42 |
+
# return {k: extended[k] for k in keys if isinstance(extended.get(k), (int, float))}
|
| 43 |
+
# except:
|
| 44 |
+
# return None
|
| 45 |
|
requirements.txt
CHANGED
|
@@ -1,3 +1,4 @@
|
|
| 1 |
gradio>=4.29.0
|
| 2 |
openai>=1.30.1
|
| 3 |
requests
|
|
|
|
|
|
| 1 |
gradio>=4.29.0
|
| 2 |
openai>=1.30.1
|
| 3 |
requests
|
| 4 |
+
httpx
|