tomirisg25 commited on
Commit
02316b8
·
verified ·
1 Parent(s): 8f07b3a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +32 -36
app.py CHANGED
@@ -21,7 +21,7 @@ for module_name, pip_name in REQUIRED_PACKAGES.items():
21
  print(f"✅ {pip_name} установлен!")
22
 
23
  # ============================================
24
- # 👑 TOMIRIS SPACE 29 v2.0 — MACRO SURPRISE ENGINE (Async, Real FRED, Fixed CPI)
25
  # ============================================
26
  import os, time, json, logging, asyncio
27
  from typing import Dict, Any, List, Optional
@@ -37,7 +37,7 @@ logger = logging.getLogger("Space29_MacroSurprise")
37
 
38
  # ================= КОНФИГУРАЦИЯ =================
39
  SYMBOLS = ["XAU/USD", "ETH/USD", "SOL/USD"]
40
- ARBITER_URL = os.getenv("SPACE18_URL", "https://tomiris-ai-name6-6.hf.space")
41
  FRED_KEY = os.getenv("FRED_KEY", "faa11c8e2e4beee08c5b966e8b63a513")
42
  NEWSAPI_KEY = os.getenv("NEWSAPI_KEY", "948c7816beea47baa23b054592472d0e")
43
 
@@ -91,15 +91,12 @@ async def fetch_fred_series(series_id: str, months: int = 13) -> List[Dict]:
91
  return []
92
 
93
  def get_yoy_change(data: List[Dict], current_month: str) -> Optional[float]:
94
- """Считает YoY изменение: текущее значение vs значение 12 месяцев назад (тот же месяц)."""
95
- # Ищем записи с нужным месяцем
96
  current_val = None
97
  prev_val = None
98
  for item in data:
99
  date = item['date']
100
  if date == current_month:
101
  current_val = item['value']
102
- # Тот же месяц, год назад (YYYY-1)
103
  year_ago = str(int(date[:4]) - 1) + date[4:]
104
  if date == year_ago and date[:7] == current_month[:7]:
105
  prev_val = item['value']
@@ -149,46 +146,41 @@ async def analyze_macro_surprises() -> Dict:
149
  today = datetime.now(timezone.utc)
150
  current_month_str = today.strftime("%Y-%m")
151
 
152
- # Загружаем FRED параллельно
153
  cpi_data = await fetch_fred_series("CPIAUCSL", 13)
154
  core_cpi_data = await fetch_fred_series("CPILFESL", 13)
155
  unemp_data = await fetch_fred_series("UNRATE", 6)
156
- nfp_data = await fetch_fred_series("PAYEMS", 3) # Non-Farm Payrolls
157
- gdp_data = await fetch_fred_series("GDP", 3) # GDP (квартальный, но берём последний)
158
- ism_data = await fetch_fred_series("NAPM", 3) # ISM Manufacturing
159
- retail_data = await fetch_fred_series("RSAFS", 3) # Retail Sales
160
- durable_data = await fetch_fred_series("DGORDER", 3) # Durable Goods
161
  fomc_surprise = await fetch_fomc_surprise()
162
 
163
  surprises = []
164
  total_score = 0.0
165
  weights = {"CPI_YOY": 0.30, "NFP": 0.25, "FOMC": 0.20, "ISM_MANUF": 0.10, "GDP_QOQ": 0.10, "RETAIL_SALES": 0.05}
166
 
167
- # CPI YoY (корректный)
168
  cpi_yoy = get_yoy_change(cpi_data, current_month_str)
169
  if cpi_yoy is not None:
170
  s = calc_surprise(cpi_yoy, CONSENSUS["CPI_YOY"])
171
- impact = s['impact'] * (1 if s['direction'] == 'NEGATIVE' else -0.5) # высокая инфляция = риск-офф
172
  total_score += impact * weights["CPI_YOY"]
173
  surprises.append({"indicator": "CPI_YOY", "actual": round(cpi_yoy, 2), "consensus": CONSENSUS["CPI_YOY"], "surprise": s})
174
 
175
- # NFP (последний месяц)
176
  if nfp_data:
177
- nfp_actual = nfp_data[0]['value'] # абсолютное значение в тысячах
178
  s = calc_surprise(nfp_actual, CONSENSUS["NFP"])
179
- impact = s['impact'] * (1 if s['direction'] == 'POSITIVE' else -1) # высокий NFP = риск-он
180
  total_score += impact * weights["NFP"]
181
  surprises.append({"indicator": "NFP", "actual": int(nfp_actual), "consensus": CONSENSUS["NFP"], "surprise": s})
182
 
183
- # GDP (квартальный, берём последний)
184
  if gdp_data:
185
- gdp_actual = gdp_data[0]['value'] # квартальное изменение в %
186
  s = calc_surprise(gdp_actual, CONSENSUS["GDP_QOQ"])
187
  impact = s['impact'] * (1 if s['direction'] == 'POSITIVE' else -1)
188
  total_score += impact * weights["GDP_QOQ"]
189
  surprises.append({"indicator": "GDP_QOQ", "actual": round(gdp_actual, 2), "consensus": CONSENSUS["GDP_QOQ"], "surprise": s})
190
 
191
- # ISM Manufacturing
192
  if ism_data:
193
  ism_actual = ism_data[0]['value']
194
  s = calc_surprise(ism_actual, CONSENSUS["ISM_MANUF"])
@@ -196,7 +188,6 @@ async def analyze_macro_surprises() -> Dict:
196
  total_score += impact * weights["ISM_MANUF"]
197
  surprises.append({"indicator": "ISM_MANUF", "actual": round(ism_actual, 2), "consensus": CONSENSUS["ISM_MANUF"], "surprise": s})
198
 
199
- # Retail Sales
200
  if retail_data:
201
  retail_actual = retail_data[0]['value']
202
  s = calc_surprise(retail_actual, CONSENSUS["RETAIL_SALES"])
@@ -204,7 +195,6 @@ async def analyze_macro_surprises() -> Dict:
204
  total_score += impact * weights["RETAIL_SALES"]
205
  surprises.append({"indicator": "RETAIL_SALES", "actual": round(retail_actual, 2), "consensus": CONSENSUS["RETAIL_SALES"], "surprise": s})
206
 
207
- # FOMC
208
  if fomc_surprise['impact'] != 0:
209
  total_score += fomc_surprise['impact'] * weights["FOMC"]
210
  surprises.append({"indicator": "FOMC", "signal": fomc_surprise['direction'], "impact": fomc_surprise['impact']})
@@ -223,7 +213,6 @@ async def analyze_macro_surprises() -> Dict:
223
  regime, direction = "NEUTRAL", "WAIT"
224
  confidence = 0.0
225
 
226
- # Сохраняем историю
227
  SURPRISE_HISTORY.append({
228
  "timestamp": today.isoformat(),
229
  "surprise_index": round(surprise_index, 2),
@@ -241,12 +230,30 @@ async def analyze_macro_surprises() -> Dict:
241
  "total_score": round(total_score, 2)
242
  }
243
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  # ================= ГЛАВНЫЙ СИГНАЛ =================
245
  async def get_macro_surprise_signal() -> Dict[str, Any]:
246
  start = time.time()
247
  analysis = await analyze_macro_surprises()
248
  latency = int((time.time() - start) * 1000)
249
 
 
 
 
 
250
  result = {
251
  "space": "space_29_macro_surprise",
252
  "timestamp": int(time.time()),
@@ -255,22 +262,11 @@ async def get_macro_surprise_signal() -> Dict[str, Any]:
255
  "latency_ms": latency
256
  }
257
 
258
- # Отправка в Arbiter
259
- try:
260
- await http_client.post(f"{ARBITER_URL}/log_signal", json={
261
- "space": "space_29_macro_surprise",
262
- "symbol": "XAU/USD",
263
- "signal": result["signals"]["XAU/USD"],
264
- "surprise_details": analysis
265
- })
266
- except:
267
- pass
268
-
269
  logger.info(f"📈 Macro Surprise: Index={analysis['surprise_index']:.1f} Regime={analysis['market_regime']}")
270
  return result
271
 
272
  # ================= FASTAPI =================
273
- app = FastAPI(title="Tomiris Space 29 v2.0 — Macro Surprise Engine")
274
 
275
  @app.on_event("startup")
276
  async def startup(): pass
@@ -280,7 +276,7 @@ async def shutdown(): await http_client.aclose()
280
 
281
  @app.get("/health")
282
  async def health():
283
- return {"status": "operational", "version": "2.0", "async": True, "no_mt5": True,
284
  "indicators": list(CONSENSUS.keys()), "history_length": len(SURPRISE_HISTORY)}
285
 
286
  @app.get("/consilium")
@@ -303,4 +299,4 @@ if __name__ == "__main__":
303
  import uvicorn
304
  uvicorn.run(app, host="0.0.0.0", port=7860)
305
 
306
- print("🚀 SPACE 29 v2.0 — MACRO SURPRISE ENGINE (REAL FRED, ASYNC) ЗАПУЩЕН!")
 
21
  print(f"✅ {pip_name} установлен!")
22
 
23
  # ============================================
24
+ # 👑 TOMIRIS SPACE 29 v2.1 — MACRO SURPRISE ENGINE (Hub-Connected)
25
  # ============================================
26
  import os, time, json, logging, asyncio
27
  from typing import Dict, Any, List, Optional
 
37
 
38
  # ================= КОНФИГУРАЦИЯ =================
39
  SYMBOLS = ["XAU/USD", "ETH/USD", "SOL/USD"]
40
+ HUB_URL = os.getenv("SPACE17_URL", "https://tomiris-ai-name5-5.hf.space")
41
  FRED_KEY = os.getenv("FRED_KEY", "faa11c8e2e4beee08c5b966e8b63a513")
42
  NEWSAPI_KEY = os.getenv("NEWSAPI_KEY", "948c7816beea47baa23b054592472d0e")
43
 
 
91
  return []
92
 
93
  def get_yoy_change(data: List[Dict], current_month: str) -> Optional[float]:
 
 
94
  current_val = None
95
  prev_val = None
96
  for item in data:
97
  date = item['date']
98
  if date == current_month:
99
  current_val = item['value']
 
100
  year_ago = str(int(date[:4]) - 1) + date[4:]
101
  if date == year_ago and date[:7] == current_month[:7]:
102
  prev_val = item['value']
 
146
  today = datetime.now(timezone.utc)
147
  current_month_str = today.strftime("%Y-%m")
148
 
 
149
  cpi_data = await fetch_fred_series("CPIAUCSL", 13)
150
  core_cpi_data = await fetch_fred_series("CPILFESL", 13)
151
  unemp_data = await fetch_fred_series("UNRATE", 6)
152
+ nfp_data = await fetch_fred_series("PAYEMS", 3)
153
+ gdp_data = await fetch_fred_series("GDP", 3)
154
+ ism_data = await fetch_fred_series("NAPM", 3)
155
+ retail_data = await fetch_fred_series("RSAFS", 3)
156
+ durable_data = await fetch_fred_series("DGORDER", 3)
157
  fomc_surprise = await fetch_fomc_surprise()
158
 
159
  surprises = []
160
  total_score = 0.0
161
  weights = {"CPI_YOY": 0.30, "NFP": 0.25, "FOMC": 0.20, "ISM_MANUF": 0.10, "GDP_QOQ": 0.10, "RETAIL_SALES": 0.05}
162
 
 
163
  cpi_yoy = get_yoy_change(cpi_data, current_month_str)
164
  if cpi_yoy is not None:
165
  s = calc_surprise(cpi_yoy, CONSENSUS["CPI_YOY"])
166
+ impact = s['impact'] * (1 if s['direction'] == 'NEGATIVE' else -0.5)
167
  total_score += impact * weights["CPI_YOY"]
168
  surprises.append({"indicator": "CPI_YOY", "actual": round(cpi_yoy, 2), "consensus": CONSENSUS["CPI_YOY"], "surprise": s})
169
 
 
170
  if nfp_data:
171
+ nfp_actual = nfp_data[0]['value']
172
  s = calc_surprise(nfp_actual, CONSENSUS["NFP"])
173
+ impact = s['impact'] * (1 if s['direction'] == 'POSITIVE' else -1)
174
  total_score += impact * weights["NFP"]
175
  surprises.append({"indicator": "NFP", "actual": int(nfp_actual), "consensus": CONSENSUS["NFP"], "surprise": s})
176
 
 
177
  if gdp_data:
178
+ gdp_actual = gdp_data[0]['value']
179
  s = calc_surprise(gdp_actual, CONSENSUS["GDP_QOQ"])
180
  impact = s['impact'] * (1 if s['direction'] == 'POSITIVE' else -1)
181
  total_score += impact * weights["GDP_QOQ"]
182
  surprises.append({"indicator": "GDP_QOQ", "actual": round(gdp_actual, 2), "consensus": CONSENSUS["GDP_QOQ"], "surprise": s})
183
 
 
184
  if ism_data:
185
  ism_actual = ism_data[0]['value']
186
  s = calc_surprise(ism_actual, CONSENSUS["ISM_MANUF"])
 
188
  total_score += impact * weights["ISM_MANUF"]
189
  surprises.append({"indicator": "ISM_MANUF", "actual": round(ism_actual, 2), "consensus": CONSENSUS["ISM_MANUF"], "surprise": s})
190
 
 
191
  if retail_data:
192
  retail_actual = retail_data[0]['value']
193
  s = calc_surprise(retail_actual, CONSENSUS["RETAIL_SALES"])
 
195
  total_score += impact * weights["RETAIL_SALES"]
196
  surprises.append({"indicator": "RETAIL_SALES", "actual": round(retail_actual, 2), "consensus": CONSENSUS["RETAIL_SALES"], "surprise": s})
197
 
 
198
  if fomc_surprise['impact'] != 0:
199
  total_score += fomc_surprise['impact'] * weights["FOMC"]
200
  surprises.append({"indicator": "FOMC", "signal": fomc_surprise['direction'], "impact": fomc_surprise['impact']})
 
213
  regime, direction = "NEUTRAL", "WAIT"
214
  confidence = 0.0
215
 
 
216
  SURPRISE_HISTORY.append({
217
  "timestamp": today.isoformat(),
218
  "surprise_index": round(surprise_index, 2),
 
230
  "total_score": round(total_score, 2)
231
  }
232
 
233
+ # ================= ОТПРАВКА В HUB =================
234
+ async def send_signal_to_hub(symbol: str, direction: str, confidence: float):
235
+ try:
236
+ await http_client.post(f"{HUB_URL}/signal", json={
237
+ "space": "space_29_macro_surprise",
238
+ "symbol": symbol,
239
+ "direction": direction,
240
+ "confidence": confidence,
241
+ "raw": json.dumps({"source": "space_29_macro_surprise"})
242
+ })
243
+ logger.info(f"📤 {symbol}: {direction} conf={confidence:.3f} отправлен в Hub")
244
+ except Exception as e:
245
+ logger.error(f"Ошибка отправки в Hub: {e}")
246
+
247
  # ================= ГЛАВНЫЙ СИГНАЛ =================
248
  async def get_macro_surprise_signal() -> Dict[str, Any]:
249
  start = time.time()
250
  analysis = await analyze_macro_surprises()
251
  latency = int((time.time() - start) * 1000)
252
 
253
+ # Отправка сигналов для всех трёх символов в Hub
254
+ for sym in SYMBOLS:
255
+ await send_signal_to_hub(sym, analysis['direction'], analysis['confidence'])
256
+
257
  result = {
258
  "space": "space_29_macro_surprise",
259
  "timestamp": int(time.time()),
 
262
  "latency_ms": latency
263
  }
264
 
 
 
 
 
 
 
 
 
 
 
 
265
  logger.info(f"📈 Macro Surprise: Index={analysis['surprise_index']:.1f} Regime={analysis['market_regime']}")
266
  return result
267
 
268
  # ================= FASTAPI =================
269
+ app = FastAPI(title="Tomiris Space 29 v2.1 — Macro Surprise Engine (Hub)")
270
 
271
  @app.on_event("startup")
272
  async def startup(): pass
 
276
 
277
  @app.get("/health")
278
  async def health():
279
+ return {"status": "operational", "version": "2.1", "hub_connected": True,
280
  "indicators": list(CONSENSUS.keys()), "history_length": len(SURPRISE_HISTORY)}
281
 
282
  @app.get("/consilium")
 
299
  import uvicorn
300
  uvicorn.run(app, host="0.0.0.0", port=7860)
301
 
302
+ print("🚀 SPACE 29 v2.1 — MACRO SURPRISE ENGINE (Hub-Connected) ЗАПУЩЕН!")