account/internal/pipeline/openfigi.go
GnomeZworc d9581d7f7e
price pipeline
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
2026-06-13 12:33:39 +02:00

75 lines
1.8 KiB
Go

package pipeline
import (
"bytes"
"context"
"encoding/json"
"fmt"
"net/http"
)
// exchSuffix mappe le code bourse OpenFIGI vers le suffixe Yahoo Finance
var exchSuffix = map[string]string{
"FP": ".PA", // Euronext Paris
"GY": ".DE", // Xetra
"LN": ".L", // London
"SM": ".MC", // Madrid
"IM": ".MI", // Milan
"NA": ".AS", // Amsterdam
"BB": ".BR", // Bruxelles
"UN": "", // NYSE
"UQ": "", // NASDAQ
"UW": "", // NASDAQ (alt)
}
type openFIGIRequest struct {
IDType string `json:"idType"`
IDValue string `json:"idValue"`
}
type openFIGIData struct {
Ticker string `json:"ticker"`
ExchCode string `json:"exchCode"`
Name string `json:"name"`
}
type openFIGIResult struct {
Data []openFIGIData `json:"data"`
Error string `json:"error"`
}
// ResolveISIN résout un ISIN en ticker Yahoo Finance via OpenFIGI.
func ResolveISIN(ctx context.Context, apiKey, isin string) (string, error) {
body, _ := json.Marshal([]openFIGIRequest{{IDType: "ID_ISIN", IDValue: isin}})
req, err := http.NewRequestWithContext(ctx, http.MethodPost,
"https://api.openfigi.com/v3/mapping", bytes.NewReader(body))
if err != nil {
return "", err
}
req.Header.Set("Content-Type", "application/json")
if apiKey != "" {
req.Header.Set("X-OPENFIGI-APIKEY", apiKey)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
var results []openFIGIResult
if err := json.NewDecoder(resp.Body).Decode(&results); err != nil {
return "", fmt.Errorf("decode openfigi response: %w", err)
}
if len(results) == 0 || len(results[0].Data) == 0 {
return "", fmt.Errorf("no result for ISIN %s", isin)
}
if results[0].Error != "" {
return "", fmt.Errorf("openfigi error: %s", results[0].Error)
}
d := results[0].Data[0]
suffix := exchSuffix[d.ExchCode]
return d.Ticker + suffix, nil
}