QAway-to commited on
Commit
e63adc7
·
1 Parent(s): d5241ad

without k_metrics

Browse files
Files changed (4) hide show
  1. SYSTEM_PROMPT.py +20 -0
  2. analyzer.py +40 -24
  3. app.py +49 -49
  4. fetch.py +33 -0
SYSTEM_PROMPT.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ SYSTEM_PROMPT = (
3
+ "Ты — опытный финансовый аналитик и инвестиционный советник. "
4
+ "Твоя задача — анализировать ключевые метрики инвестиционных портфелей и давать содержательные, прямолинейные и живые комментарии, которые легко воспринимаются даже непрофессионалами. "
5
+ "Твоя сила — в способности объяснять сложное просто, без лишней терминологии и формальной канцелярщины.\n\n"
6
+
7
+ "Формируй ответы уверенно, избегай сухих, повторяющихся формулировок. Не начинай каждый абзац с 'Это означает...', 'Это говорит о том, что...', 'Это хороший показатель...' — "
8
+ "такие обороты утомляют и делают речь однообразной. Вариативность важна. Используй живой язык, строй выводы, делай переходы между метриками логично и естественно.\n\n"
9
+
10
+ "Если метрика высокая — обозначь, чем это выгодно для инвестора. Если слабая — не скрывай риски и ограничения. Не бойся критиковать стратегию. "
11
+ "Будь честным, как на встрече с клиентом: без лишнего позитивного окраса, только по делу. Допускается лёгкая ирония, если она помогает донести суть.\n\n"
12
+
13
+ "Ты можешь делать предположения и гипотезы: например, как стратегия поведёт себя в растущем рынке, при кризисе, при высокой инфляции или волатильности. "
14
+ "Портфель может быть описан как 'агрессивный', 'консервативный', 'высокочастотный', 'рискованный', 'подходит для пассивного дохода' и т.д. — не бойся давать такие оценки.\n\n"
15
+
16
+ "Пиши как будто общаешься напрямую с человеком, который хочет понять: стоит ли ему доверять деньги этой стратегии. В конце — можешь кратко подытожить общую картину и настроение по портфелю.\n\n"
17
+
18
+ "Всё это должно выглядеть как профессиональный, но понятный разговор — не как слайд с конференции. В очередном описании ключевой метрики, старайся применять иные формулировки, нежели те, которые применял для описания предыдущей."
19
+ "При сравнении двух портфелей, СТРОГО используй 'портфель А' и портфель B', выделяй сильные и слабые стороны каждого, делай акцент на различиях и потенциальных рисках."
20
+ )
analyzer.py CHANGED
@@ -1,32 +1,48 @@
1
- #Извлечение UUID из строки
2
- def extract_portfolio_id(text: str) -> str | None:
3
- match = re.search(
4
- r"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}",
5
- text
6
- )
7
- return match.group(0) if match else None
8
 
9
- def fetch_metrics(portfolio_id: str) -> dict | None:
10
  try:
 
11
  url = f"https://api.tradelink.pro/portfolio/get?portfolioId={portfolio_id}&extended=1&declaration=1&step=day&lang=en&incViews=1"
12
  response = requests.get(url)
13
- response.raise_for_status()
14
- extended = response.json().get("data", {}).get("extended", {})
15
- keys = [
16
- # 🔹 Доходность и риск
17
- "alphaRatio", "betaRatio", "cagr", "sharpe", "sortino", "volatility",
18
- "kSortino", "kCalmar", "kSharpe",
19
 
20
- # 🔹 Просадки
21
- "maxDD", "mddDuration", "maxBalance",
 
22
 
23
- # 🔹 Поведение стратегии
24
- "losingDays", "winningDays", "selfProfitRate",
 
 
 
25
 
26
- # 🔹 Актуальные показатели доходности
27
- "lastWeekNetProfit", "lastMonthNetProfit", "lastQuarterGrowth", "lastYearNetGrowth"
28
- ]
29
 
30
- return {k: extended[k] for k in keys if isinstance(extended.get(k), (int, float))}
31
- except:
32
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import SYSTEM_PROMPT
2
+ # Анализ одного портфеля
3
+ def analyze_portfolio_streaming(text: str):
4
+ portfolio_id = extract_portfolio_id(text)
5
+ if not portfolio_id:
6
+ yield "❗ Укажите корректный portfolioId или ссылку."
7
+ return
8
 
 
9
  try:
10
+ # Получение JSON по API
11
  url = f"https://api.tradelink.pro/portfolio/get?portfolioId={portfolio_id}&extended=1&declaration=1&step=day&lang=en&incViews=1"
12
  response = requests.get(url)
13
+ json_data = response.json()
14
+ extended = json_data.get("data", {}).get("extended", {})
 
 
 
 
15
 
16
+ if not extended:
17
+ yield " Метрики не найдены в ответе API."
18
+ return
19
 
20
+ # Передаём все числовые метрики, без фильтрации
21
+ metrics = {k: v for k, v in extended.items() if isinstance(v, (int, float))}
22
+ if not metrics:
23
+ yield "❗ Нет числовых метрик для анализа."
24
+ return
25
 
26
+ metrics_text = ", ".join([f"{k}: {v}" for k, v in metrics.items()])
27
+ prompt = f"""Вот метрики портфеля: {metrics_text}.
28
+ Проанализируй их и объясни сильные и слабые стороны на русском языке, как финансовый аналитик."""
29
 
30
+ # Запрос к модели
31
+ response_llm = client.chat.completions.create(
32
+ model="nasiruddin15/Mistral-dolphin-2.8-grok-instract-2-7B-slerp",
33
+ messages=[
34
+ {"role": "system", "content": SYSTEM_PROMPT},
35
+ {"role": "user", "content": prompt}
36
+ ],
37
+ stream=True
38
+ )
39
+
40
+ partial = ""
41
+ for chunk in response_llm:
42
+ delta = chunk.choices[0].delta.content
43
+ if delta:
44
+ partial += delta
45
+ yield partial
46
+
47
+ except Exception as e:
48
+ yield f"❌ Ошибка при обработке: {e}"
app.py CHANGED
@@ -2,8 +2,8 @@ import gradio as gr
2
  import requests
3
  import re
4
  import os
5
- from analyzer import fetch_metrics
6
- # from analyzer import extract_portfolio_id
7
  from openai import OpenAI
8
 
9
  api_key = os.getenv("featherless") #
@@ -105,7 +105,7 @@ def extract_portfolio_id(text: str) -> str | None:
105
  # response_llm = client.chat.completions.create(
106
  # model="meta-llama/Meta-Llama-3.1-8B-Instruct",
107
  # messages=[
108
- # {"role": "system", "content": SYSTEM_PROMPT},
109
  # {"role": "user", "content": prompt}
110
  # ],
111
  # stream=True
@@ -120,52 +120,52 @@ def extract_portfolio_id(text: str) -> str | None:
120
  # yield partial
121
 
122
  # Анализ одного портфеля
123
- def analyze_portfolio_streaming(text: str):
124
- portfolio_id = extract_portfolio_id(text)
125
- if not portfolio_id:
126
- yield "❗ Укажите корректный portfolioId или ссылку."
127
- return
128
-
129
- try:
130
- # Получение JSON по API
131
- url = f"https://api.tradelink.pro/portfolio/get?portfolioId={portfolio_id}&extended=1&declaration=1&step=day&lang=en&incViews=1"
132
- response = requests.get(url)
133
- json_data = response.json()
134
- extended = json_data.get("data", {}).get("extended", {})
135
-
136
- if not extended:
137
- yield "❗ Метрики не найдены в ответе API."
138
- return
139
-
140
- # Передаём все числовые метрики, без фильтрации
141
- metrics = {k: v for k, v in extended.items() if isinstance(v, (int, float))}
142
- if not metrics:
143
- yield "❗ Нет числовых метрик для анализа."
144
- return
145
-
146
- metrics_text = ", ".join([f"{k}: {v}" for k, v in metrics.items()])
147
- prompt = f"""Вот метрики портфеля: {metrics_text}.
148
- Проанализируй их и объясни сильные и слабые стороны на русском языке, как финансовый аналитик."""
149
-
150
- # Запрос к модели
151
- response_llm = client.chat.completions.create(
152
- model="nasiruddin15/Mistral-dolphin-2.8-grok-instract-2-7B-slerp",
153
- messages=[
154
- {"role": "system", "content": SYSTEM_PROMPT},
155
- {"role": "user", "content": prompt}
156
- ],
157
- stream=True
158
- )
159
-
160
- partial = ""
161
- for chunk in response_llm:
162
- delta = chunk.choices[0].delta.content
163
- if delta:
164
- partial += delta
165
- yield partial
166
-
167
- except Exception as e:
168
- yield f"❌ Ошибка при обработке: {e}"
169
 
170
 
171
  # Сравнение двух портфелей
 
2
  import requests
3
  import re
4
  import os
5
+ from analyzer import analyze_portfolio_streaming
6
+ from fetch import fetch_metrics
7
  from openai import OpenAI
8
 
9
  api_key = os.getenv("featherless") #
 
105
  # response_llm = client.chat.completions.create(
106
  # model="meta-llama/Meta-Llama-3.1-8B-Instruct",
107
  # messages=[
108
+ # {"role": "system", "content": SYSTEM_PROMPT.py},
109
  # {"role": "user", "content": prompt}
110
  # ],
111
  # stream=True
 
120
  # yield partial
121
 
122
  # Анализ одного портфеля
123
+ # def analyze_portfolio_streaming(text: str):
124
+ # portfolio_id = extract_portfolio_id(text)
125
+ # if not portfolio_id:
126
+ # yield "❗ Укажите корректный portfolioId или ссылку."
127
+ # return
128
+ #
129
+ # try:
130
+ # # Получение JSON по API
131
+ # url = f"https://api.tradelink.pro/portfolio/get?portfolioId={portfolio_id}&extended=1&declaration=1&step=day&lang=en&incViews=1"
132
+ # response = requests.get(url)
133
+ # json_data = response.json()
134
+ # extended = json_data.get("data", {}).get("extended", {})
135
+ #
136
+ # if not extended:
137
+ # yield "❗ Метрики не найдены в ответе API."
138
+ # return
139
+ #
140
+ # # Передаём все числовые метрики, без фильтрации
141
+ # metrics = {k: v for k, v in extended.items() if isinstance(v, (int, float))}
142
+ # if not metrics:
143
+ # yield "❗ Нет числовых метрик для анализа."
144
+ # return
145
+ #
146
+ # metrics_text = ", ".join([f"{k}: {v}" for k, v in metrics.items()])
147
+ # prompt = f"""Вот метрики портфеля: {metrics_text}.
148
+ # Проанализируй их и объясни сильные и слабые стороны на русском языке, как финансовый аналитик."""
149
+ #
150
+ # # Запрос к модели
151
+ # response_llm = client.chat.completions.create(
152
+ # model="nasiruddin15/Mistral-dolphin-2.8-grok-instract-2-7B-slerp",
153
+ # messages=[
154
+ # {"role": "system", "content": SYSTEM_PROMPT},
155
+ # {"role": "user", "content": prompt}
156
+ # ],
157
+ # stream=True
158
+ # )
159
+ #
160
+ # partial = ""
161
+ # for chunk in response_llm:
162
+ # delta = chunk.choices[0].delta.content
163
+ # if delta:
164
+ # partial += delta
165
+ # yield partial
166
+ #
167
+ # except Exception as e:
168
+ # yield f"❌ Ошибка при обработке: {e}"
169
 
170
 
171
  # Сравнение двух портфелей
fetch.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #Извлечение UUID из строки
2
+ def extract_portfolio_id(text: str) -> str | None:
3
+ match = re.search(
4
+ r"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}",
5
+ text
6
+ )
7
+ return match.group(0) if match else None
8
+
9
+ def fetch_metrics(portfolio_id: str) -> dict | None:
10
+ try:
11
+ url = f"https://api.tradelink.pro/portfolio/get?portfolioId={portfolio_id}&extended=1&declaration=1&step=day&lang=en&incViews=1"
12
+ response = requests.get(url)
13
+ response.raise_for_status()
14
+ extended = response.json().get("data", {}).get("extended", {})
15
+ keys = [
16
+ # 🔹 Доходность и риск
17
+ "alphaRatio", "betaRatio", "cagr", "sharpe", "sortino", "volatility",
18
+ "kSortino", "kCalmar", "kSharpe",
19
+
20
+ # 🔹 Просадки
21
+ "maxDD", "mddDuration", "maxBalance",
22
+
23
+ # 🔹 Поведение стратегии
24
+ "losingDays", "winningDays", "selfProfitRate",
25
+
26
+ # 🔹 Актуальные показатели доходности
27
+ "lastWeekNetProfit", "lastMonthNetProfit", "lastQuarterGrowth", "lastYearNetGrowth"
28
+ ]
29
+
30
+ return {k: extended[k] for k in keys if isinstance(extended.get(k), (int, float))}
31
+ except:
32
+ return None
33
+