Files
OpenFin/backend/routers/config.py
2026-07-21 12:24:52 +02:00

158 lines
5.4 KiB
Python

from fastapi import APIRouter
from pydantic import BaseModel
from typing import Dict, Any, Optional
import os
from services.database import get_all_config, set_config, get_config, get_sources, update_sources, get_analysis_config, save_analysis_config
router = APIRouter(prefix="/api/config", tags=["config"])
class ApiKeysRequest(BaseModel):
openai_api_key: Optional[str] = None
newsapi_key: Optional[str] = None
eia_api_key: Optional[str] = None
fred_api_key: Optional[str] = None
fmp_api_key: Optional[str] = None
calendar_refresh_h: Optional[str] = None
class SourcesRequest(BaseModel):
sources: Dict[str, Any]
class SettingsRequest(BaseModel):
ai_enabled: Optional[str] = None
ai_auto_rescore: Optional[str] = None
class AnalysisConfigRequest(BaseModel):
top_n: Optional[int] = None
category_filter: Optional[str] = None
template: Optional[str] = None
@router.get("/")
def get_config_all():
return get_all_config()
@router.get("/sources")
def list_sources():
return get_sources()
@router.put("/sources")
def update_sources_endpoint(req: SourcesRequest):
update_sources(req.sources)
return {"status": "ok", "updated": len(req.sources)}
@router.put("/api-keys")
def update_api_keys(req: ApiKeysRequest):
updated = []
if req.openai_api_key is not None:
set_config("openai_api_key", req.openai_api_key)
os.environ["OPENAI_API_KEY"] = req.openai_api_key
updated.append("openai")
if req.newsapi_key is not None:
set_config("newsapi_key", req.newsapi_key)
updated.append("newsapi")
if req.eia_api_key is not None:
set_config("eia_api_key", req.eia_api_key)
updated.append("eia")
if req.fred_api_key is not None:
set_config("fred_api_key", req.fred_api_key)
updated.append("fred")
if req.fmp_api_key is not None:
set_config("fmp_api_key", req.fmp_api_key)
updated.append("fmp")
if req.calendar_refresh_h is not None:
set_config("calendar_refresh_h", req.calendar_refresh_h)
updated.append("calendar_refresh_h")
return {"status": "ok", "updated": updated}
@router.put("/settings")
def update_settings(req: SettingsRequest):
if req.ai_enabled is not None:
set_config("ai_enabled", req.ai_enabled)
if req.ai_auto_rescore is not None:
set_config("ai_auto_rescore", req.ai_auto_rescore)
return {"status": "ok"}
@router.get("/analysis")
def get_analysis_config_endpoint():
return get_analysis_config()
@router.put("/analysis")
def save_analysis_config_endpoint(req: AnalysisConfigRequest):
current = get_analysis_config()
if req.top_n is not None:
current["top_n"] = req.top_n
if req.category_filter is not None:
current["category_filter"] = req.category_filter
if req.template is not None:
current["template"] = req.template
save_analysis_config(current)
return {"status": "ok", "config": current}
class OptionsGateRequest(BaseModel):
iv_gate_enabled: Optional[bool] = None
iv_gate_ivr_high: Optional[float] = None
iv_gate_ivr_extreme: Optional[float] = None
iv_gate_skew_threshold: Optional[float] = None
@router.get("/options-gate")
def get_options_gate():
return {
"iv_gate_enabled": (get_config("iv_gate_enabled") or "true").lower() == "true",
"iv_gate_ivr_high": float(get_config("iv_gate_ivr_high") or 60),
"iv_gate_ivr_extreme": float(get_config("iv_gate_ivr_extreme") or 80),
"iv_gate_skew_threshold": float(get_config("iv_gate_skew_threshold") or 8),
}
@router.put("/options-gate")
def save_options_gate(req: OptionsGateRequest):
if req.iv_gate_enabled is not None:
set_config("iv_gate_enabled", "true" if req.iv_gate_enabled else "false")
if req.iv_gate_ivr_high is not None:
set_config("iv_gate_ivr_high", str(req.iv_gate_ivr_high))
if req.iv_gate_ivr_extreme is not None:
set_config("iv_gate_ivr_extreme", str(req.iv_gate_ivr_extreme))
if req.iv_gate_skew_threshold is not None:
set_config("iv_gate_skew_threshold", str(req.iv_gate_skew_threshold))
return {"status": "ok"}
# ── Tech Indicators config ──────────────────────────────────────────────────
class TechIndicatorsRequest(BaseModel):
tech_indicators_enabled: Optional[bool] = None
tech_indicators_list: Optional[str] = None # comma-separated: "rsi,ma,bollinger,atr"
tech_indicators_auto_calibrate: Optional[bool] = None
@router.get("/tech-indicators")
def get_tech_indicators():
return {
"tech_indicators_enabled": (get_config("tech_indicators_enabled") or "true").lower() == "true",
"tech_indicators_list": get_config("tech_indicators_list") or "rsi,ma,bollinger,atr",
"tech_indicators_auto_calibrate": (get_config("tech_indicators_auto_calibrate") or "true").lower() == "true",
}
@router.put("/tech-indicators")
def save_tech_indicators(req: TechIndicatorsRequest):
if req.tech_indicators_enabled is not None:
set_config("tech_indicators_enabled", "true" if req.tech_indicators_enabled else "false")
if req.tech_indicators_list is not None:
set_config("tech_indicators_list", req.tech_indicators_list)
if req.tech_indicators_auto_calibrate is not None:
set_config("tech_indicators_auto_calibrate", "true" if req.tech_indicators_auto_calibrate else "false")
return {"status": "ok"}