feat: saxo price

This commit is contained in:
OpenSquared
2026-07-30 17:43:49 +02:00
parent 40af21ede4
commit b8e2a5169c
5 changed files with 151 additions and 10 deletions

View File

@@ -17,6 +17,7 @@ from services.instrument_service import (
update_instrument_drivers,
update_instrument_saxo_link,
quick_add_instrument_from_watchlist,
add_manual_instrument,
)
class DriverUpdate(BaseModel):
@@ -30,6 +31,14 @@ class SaxoLinkBody(BaseModel):
class QuickAddBody(BaseModel):
ticker: str
class AddManualBody(BaseModel):
id: str
name: str
category: str
yf_ticker: Optional[str] = None
saxo_quote_symbol: Optional[str] = None
router = APIRouter(prefix="/api/instruments", tags=["instruments"])
@@ -51,6 +60,20 @@ def quick_add(body: QuickAddBody) -> Dict[str, Any]:
raise HTTPException(status_code=404, detail=str(e))
@router.post("/add-manual")
def add_manual(body: AddManualBody) -> Dict[str, Any]:
"""Create a standalone Instrument Analysis entry from scratch — Config page's "Ajouter
un ticker" zone, for instruments that aren't in the Cockpit Watchlist (so quick-add
doesn't apply) and don't warrant hand-authoring an instruments.json entry."""
try:
return add_manual_instrument(
body.id, name=body.name, category=body.category,
yf_ticker=body.yf_ticker, saxo_quote_symbol=body.saxo_quote_symbol,
)
except ValueError as e:
raise HTTPException(status_code=409, detail=str(e))
@router.get("/{instrument_id}/snapshot")
async def instrument_snapshot(
instrument_id: str,

View File

@@ -227,6 +227,34 @@ def quick_add_instrument_from_watchlist(ticker: str) -> Dict[str, Any]:
return {"id": uid, "created": True}
def add_manual_instrument(
instrument_id: str, name: str, category: str,
yf_ticker: Optional[str] = None, saxo_quote_symbol: Optional[str] = None,
) -> Dict[str, Any]:
"""Create a standalone Instrument Analysis entry directly (Config page's "Ajouter un
ticker" zone) — same instrument_overrides row shape as quick_add_instrument_from_watchlist
above, but without requiring a pre-existing Cockpit Watchlist row, since the whole point
here is to add a ticker that isn't tracked anywhere yet (e.g. EURCHF, resolved live
against Saxo just before this call). Rejects an id that already resolves — use the
existing drivers/saxo-link editors to modify it instead of silently overwriting."""
global _configs
if _configs is None:
_load_configs()
uid = instrument_id.strip().upper()
if uid in _configs:
raise ValueError(f"'{uid}' existe déjà dans Instrument Analysis")
from services.database import set_instrument_override_quick_add
set_instrument_override_quick_add(
uid, name=name.strip() or uid, yf_ticker=(yf_ticker or uid).strip().upper(),
category=category, saxo_quote_symbol=saxo_quote_symbol,
)
_load_configs()
logger.info(f"[instrument_service] Manually added {uid} (category={category}, saxo={saxo_quote_symbol})")
return {"id": uid, "created": True}
# ── DataFrame helpers ──────────────────────────────────────────────────────────
def _ohlcv_to_df(records: List[Dict]) -> pd.DataFrame: