Una librería completa en Go para acceder a datos financieros de la Bolsa de Comercio de Buenos Aires (BYMA - Bolsas y Mercados Argentinos) a través de su API pública gratuita.
Te da acceso a datos del mercado financiero argentino con tipado fuerte, concurrencia segura, caché incorporado y optimizaciones de rendimiento.
English version available here
- Caché Inteligente de 5 Minutos: El almacenamiento en caché automático reduce las llamadas a la API en un 95% y mejora la velocidad 100 veces
- Búsquedas Individuales de Tickers: Obtené valores específicos sin necesidad de recuperar colecciones completas
- Operaciones por Lotes: Recuperá múltiples valores de forma eficiente en una sola operación
-
Tipado Fuerte: No más
interface{}
genéricos - estructuras adecuadas para cada instrumento financiero - Seguro para Concurrencia: Seguro para usar en múltiples goroutines con caché thread-safe
-
Compatible con Context: Todos los métodos aceptan
context.Context
para cancelación y timeouts - Lógica de Reintentos: Retroceso exponencial incorporado para llamadas resilientes a la API
- Manejo Completo de Errores: Tipos de errores personalizados con lógica de reintentos
- Acciones: Líderes (blue chips), Panel general (galpones), CEDEARs
- Renta Fija: Bonos gubernamentales, bonos corporativos, letras de corto plazo (LEBACs)
- Derivados: Contratos de opciones, futuros
- Datos Históricos: Series temporales con OHLCV (Open, High, Low, Close, Volume) para gráficos
- Datos de Mercado: Índices, resumen del mercado, estado de días hábiles
- Noticias y Financieros: Noticias del mercado, estados de resultados
Nota: "Securities" es un término financiero genérico en nuestro código Go, pero los endpoints reales de la API de BYMA son:
leading-equity
,general-equity
, ycedears
- Suite de Pruebas Completa: Servidores HTTP de prueba para testing confiable
- Benchmarks: Incluye pruebas de rendimiento
- Ejemplos: Documentación re completa con ejemplos ejecutables
go get github.com/pablocarvajal/openbymadata
📖 La documentación completa con ejemplos está disponible directamente en el código y en pkg.go.dev
go get github.com/carvalab/openbymadata
package main
import (
"context"
"fmt"
"log"
"github.com/carvalab/openbymadata"
)
func main() {
// Crear cliente (caché de 5 minutos habilitado por defecto)
client := openbymadata.NewClient()
ctx := context.Background()
// Conseguir acción específica de EEUU (CEDEAR)
aapl, err := client.GetCedear(ctx, "AAPL")
if err != nil {
log.Fatal(err)
}
fmt.Printf("🍎 AAPL: $%.2f (%.2f%%)\n", aapl.Last, aapl.Change)
// Búsqueda universal (recomendada)
security, err := client.GetSecurity(ctx, "BMA")
if err != nil {
log.Fatal(err)
}
fmt.Printf("🔍 BMA: $%.2f\n", security.Last)
}
🎯 Búsquedas Individuales: Obtené valores específicos sin descargar colecciones completas
// Búsqueda universal (funciona para cualquier tipo de valor)
security, err := client.GetSecurity(ctx, "AAPL")
// Tipos específicos
aapl, err := client.GetCedear(ctx, "AAPL") // CEDEARs (acciones de EEUU)
ggal, err := client.GetBluechip(ctx, "GGAL") // Acciones líderes argentinas
⚡ Operaciones por Lotes: Múltiples valores en una sola operación
watchlist := []string{"AAPL", "MSFT", "GOOGL", "GGAL"}
securities, err := client.GetMultipleSecurities(ctx, watchlist)
📈 Datos Históricos: Series temporales para gráficos
// Últimos 30 días
historyData, err := client.GetHistoryLastDays(ctx, "SPY", 30)
// Rango personalizado
weeklyData, err := client.GetHistory(ctx, "AAPL", "W", from, to)
💾 Caché Inteligente: Mejora de 100x en velocidad, reducción del 95% en llamadas a la API
// Conseguir todas las acciones líderes (en caché por 5 minutos)
bluechips, err := client.GetBluechips(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Encontradas %d acciones líderes:\n", len(bluechips))
for _, security := range bluechips[:5] { // Mostrar las primeras 5
fmt.Printf(" %s: $%.2f (%.2f%%)\n",
security.Symbol, security.Last, security.Change)
}
// Crear cliente con opciones personalizadas
opts := &openbymadata.ClientOptions{
Timeout: 30 * time.Second,
RetryAttempts: 5,
Logger: customLogger, // Tu implementación de logger
}
client := openbymadata.NewClient(opts)
La librería incluye ejemplos completos que demuestran todas las funcionalidades:
# Clonar el repositorio
git clone https://github.com/carvalab/openbymadata.git
cd openbymadata
# Correr el ejemplo completo (muestra todas las funcionalidades)
go run cmd/example/main.go
# O compilar y ejecutar
go build -o byma-demo cmd/example/main.go
./byma-demo
🏛️ OpenBYMAData Go Library - Complete Example
============================================================
🚀 Features: Individual ticker lookups, 5-minute caching, batch operations
📊 1. Market Status & Info
------------------------------
Market Status: 🟢 OPEN
Market Indices (15):
📈 G: 94518124.24 (0.01%)
📈 M: 2213570.17 (0.01%)
📈 SPBYCAP: 39874.07 (0.03%)
💰 2. Individual Ticker Lookups
-----------------------------------
🇺🇸 CEDEARs:
🍎 AAPL: $13825.00 (0.00%) [220ms]
Volume: 46576 | Last Update: 16:59:00
🇦🇷 Argentine Leading Equity:
🏦 GGAL: $6620.00 (-0.00%)
🔍 Universal Search:
📉 BMA: $9140.00 (-0.01%)
📈 TSLA: $28175.00 (0.04%)
❌ UNKNOWN: Not found
📦 3. Batch Operations
-------------------------
💼 Portfolio (6/6 securities) [74µs]:
🟢 AAPL : $13825.00 +0.00%
🔴 MSFT : $22100.00 -0.00%
🟢 GOOGL : $4300.00 +0.00%
🟢 TSLA : $28175.00 +0.04%
🟢 META : $38750.00 +0.01%
🔴 GGAL : $6620.00 -0.00%
💰 Total Portfolio Value: $113770.00
📋 4. Collection Data (API endpoints: leading-equity, general-equity, cedears)
--------------------------------------------------------------------------------
💎 Leading Equity (21 securities from 'leading-equity' endpoint):
🔴 ALUA: $709.00 (-0.00%) | Vol: 1171941
... and 18 more
🌎 CEDEARs (1132 securities from 'cedears' endpoint):
🟢 AAL: $7530.00 (0.01%)
... and 1129 more
🏢 General Equity (178 securities from 'general-equity' endpoint):
🟢 A3: $2500.00 (0.01%)
... and 175 more
🏛️ 5. Fixed Income & Derivatives
-----------------------------------
📊 Government Bonds: 156 instruments
Example: AL30 - $428.50
📈 Options: 2847 contracts
🔮 Futures: 23 contracts
⚡ 6. Cache Performance (5-minute automatic caching)
-------------------------------------------------------
🗄️ Cache Status:
bluechips : 21 items, age 215ms, fresh: true
cedears : 1132 items, age 256ms, fresh: true
galpones : 178 items, age 165ms, fresh: true
🏃 Cache Speed Test:
Getting AAPL again (cached)... 750ns (lightning fast!)
📈 7. Historical Data (Chart Data)
-----------------------------------
📊 Historical Data for SPY (last 30 days):
Retrieved 21 data points:
First (2024-02-15): Open=$484.21 High=$486.58 Low=$483.12 Close=$485.22 Vol=45782
Middle (2024-02-28): Open=$502.18 High=$503.47 Low=$501.25 Close=$502.87 Vol=52341
Latest (2024-03-15): Open=$518.45 High=$519.23 Low=$517.89 Close=$518.67 Vol=38945
📅 Custom Date Range (Weekly data - last 3 months):
AAPL Weekly Data - 13 weeks retrieved
Latest week (2024-03-15): Close=$182.31
🔄 Converting to HistoricalData format (if needed):
Converted 21 OHLCV data points to HistoricalData structs
First point (2024-02-15): $485.22
📰 8. News & Financial Data
------------------------------
📰 Latest News (24 items):
📄 BYMA informa cotizaciones del día
Date: 2024-03-15 18:30
📄 Resultados trimestrales empresas listadas
Date: 2024-03-15 16:45
📊 Income statements for ALUA: 8 records
🎉 Example Complete!
============================================================
✨ Features Demonstrated:
• Individual ticker lookups (GetCedear, GetBluechip, GetSecurity)
• Efficient batch operations (GetMultipleSecurities)
• Historical data & charting (GetHistory, GetHistoryLastDays)
• 5-minute automatic caching (reduces API calls by 95%)
• API endpoint mapping:
- GetBluechips() → 'leading-equity' endpoint
- GetGalpones() → 'general-equity' endpoint
- GetCedears() → 'cedears' endpoint
- GetHistory() → 'chart/historical-series/history' endpoint
• Full market data coverage (equities, bonds, derivatives)
• Real-time market news and financial data
• Thread-safe concurrent operations
• Comprehensive error handling
🚀 Production Ready:
• Context-aware operations
• Built-in retry logic
• Strongly-typed data structures
• Zero external dependencies
# Correr pruebas de ejemplo
go test -v -run "Example"
# Correr prueba de ejemplo específica
go test -v -run "ExampleClient"
Recurso | Descripción |
---|---|
📖 pkg.go.dev | Documentación principal - Referencia completa de la API con ejemplos |
🎯 example_test.go | Ejemplos ejecutables para todas las funcionalidades |
🏛️ cmd/example/main.go | Demo completa mostrando toda la funcionalidad |
💾 CACHING_GUIDE.md | Guía detallada de rendimiento del caché |
🐛 DEBUG.md | Guía de debugging y resolución de problemas |
# 🌐 Mejor opción: Visitar pkg.go.dev (ejemplos y markdown)
# https://pkg.go.dev/github.com/carvalab/openbymadata
# Documentación en terminal
go doc -all
# Correr ejemplos
go test -v -run "Example"
// Búsqueda universal (recomendada - busca en todos los tipos de valores)
security, err := client.GetSecurity(ctx, "AAPL") // Funciona para cualquier símbolo
// Tipos específicos de valores
aapl, err := client.GetCedear(ctx, "AAPL") // Acciones de EEUU (CEDEARs)
ggal, err := client.GetBluechip(ctx, "GGAL") // Acciones líderes argentinas
galpone, err := client.GetGalpone(ctx, "SYMBOL") // Panel general
bond, err := client.GetBond(ctx, "AL30") // Todos los tipos de bonos
option, err := client.GetOption(ctx, "GGAL123") // Opciones
future, err := client.GetFuture(ctx, "DOE25") // Futuros
// Conseguir múltiples valores eficientemente (usa caché compartida)
watchlist := []string{"AAPL", "MSFT", "GOOGL", "GGAL"}
securities, err := client.GetMultipleSecurities(ctx, watchlist)
// Buscar valores por símbolo parcial
results, err := client.SearchSecurities(ctx, "APP") // Encuentra símbolos que contienen "APP"
// Obtener datos históricos para los últimos 30 días (automáticamente agrega "24HS")
historyData, err := client.GetHistoryLastDays(ctx, "SPY", 30)
// Obtener datos históricos con rango de fechas personalizado
// Símbolos se normalizan automáticamente (se agrega "24HS" si no está presente)
// Resolución: "D" = diario, "W" = semanal, "M" = mensual
// from/to son time.Time (conversión a Unix automática)
from := time.Now().AddDate(0, -3, 0) // 3 meses atrás
to := time.Now() // ahora
weeklyData, err := client.GetHistory(ctx, "AAPL", "W", from, to)
// Los datos retornan OHLCV como slices separados (formato más eficiente)
for i := range len(historyData.Time) {
fmt.Printf("%s: Close=$%.2f, Volume=%d\n",
historyData.Time[i].Format("2006-01-02"), historyData.Close[i], historyData.Volume[i])
}
// Opcional: Convertir a formato estructurado si es necesario
structuredData, err := client.ConvertToHistoricalData(historyData)
for _, candle := range structuredData {
fmt.Printf("%s: Close=$%.2f\n", candle.Time.Format("2006-01-02"), candle.Close)
}
// Chequear si el mercado está operando hoy
isWorking, err := client.IsWorkingDay(ctx)
// Conseguir índices del mercado (Merval, etc.)
indices, err := client.GetIndices(ctx)
// Conseguir resumen del mercado
summary, err := client.MarketResume(ctx)
// Todos los valores de un tipo específico (en caché por 5 minutos)
bluechips, err := client.GetBluechips(ctx) // → endpoint 'leading-equity'
galpones, err := client.GetGalpones(ctx) // → endpoint 'general-equity'
cedears, err := client.GetCedears(ctx) // → endpoint 'cedears'
// Bonos gubernamentales
bonds, err := client.GetBonds(ctx)
// Letras de corto plazo (LEBACs)
shortTermBonds, err := client.GetShortTermBonds(ctx)
// Bonos corporativos
corporateBonds, err := client.GetCorporateBonds(ctx)
// Contratos de opciones
options, err := client.GetOptions(ctx)
// Contratos de futuros
futures, err := client.GetFutures(ctx)
// Noticias del mercado (en caché por 5 minutos)
news, err := client.GetNews(ctx)
// Estados de resultados para un ticker específico (en caché por símbolo)
statements, err := client.GetIncomeStatement(ctx, "GGAL")
// Conseguir información de caché
cacheInfo := client.GetCacheInfo()
fmt.Printf("Estado del caché: %+v\n", cacheInfo)
// Limpiar todos los datos en caché (fuerza llamadas frescas a la API)
client.ClearCache()
// Deshabilitar caché (no recomendado)
client := openbymadata.NewClient(&openbymadata.ClientOptions{
EnableCache: false,
})
type Security struct {
Symbol string `json:"symbol"`
Settlement string `json:"settlement"`
BidSize int64 `json:"bid_size"`
Bid float64 `json:"bid"`
Ask float64 `json:"ask"`
AskSize int64 `json:"ask_size"`
Last float64 `json:"last"`
Close float64 `json:"close"`
Change float64 `json:"change"`
Open float64 `json:"open"`
High float64 `json:"high"`
Low float64 `json:"low"`
PreviousClose float64 `json:"previous_close"`
Turnover float64 `json:"turnover"`
Volume int64 `json:"volume"`
Operations int64 `json:"operations"`
DateTime time.Time `json:"datetime"`
Group string `json:"group"`
}
type Bond struct {
// All Security fields plus:
Expiration time.Time `json:"expiration"`
}
type Option struct {
Symbol string `json:"symbol"`
// ... price fields ...
UnderlyingAsset string `json:"underlying_asset"`
Expiration time.Time `json:"expiration"`
}
# Correr todos los tests
go test ./...
# Correr tests con cobertura
go test -cover ./...
# Correr benchmarks
go test -bench=. ./...
La librería utiliza servidores HTTP de prueba para simular respuestas de la API:
func TestMyBusinessLogic(t *testing.T) {
// Create test server with mock responses
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
mockResponse := []openbymadata.Security{
{Symbol: "GGAL", Last: 150.50},
}
json.NewEncoder(w).Encode(mockResponse)
}))
defer server.Close()
// Create client pointing to test server
client := openbymadata.NewClient(&openbymadata.ClientOptions{
BaseURL: server.URL,
})
// Test your business logic
result, err := myBusinessLogic(client)
assert.NoError(t, err)
assert.Equal(t, expectedResult, result)
}
La librería proporciona un manejo completo de errores con tipos de errores personalizados:
securities, err := client.GetBluechips(ctx)
if err != nil {
if bymaErr, ok := err.(*openbymadata.BYMAError); ok {
switch bymaErr.Code {
case "TIMEOUT":
// Handle timeout
case "RATE_LIMITED":
// Handle rate limiting
case "API_UNAVAILABLE":
// Handle API unavailability
default:
log.Printf("API error: %v", bymaErr)
}
} else {
log.Printf("Unexpected error: %v", err)
}
}
- Caché Automático: Todos los datos se almacenan en caché por 5 minutos por defecto
- Mejora de Velocidad 100x: Las llamadas en caché toman microsegundos vs llamadas a la API en milisegundos
- Reducción del 95% en Llamadas a la API: Reduce drásticamente el ancho de banda y el rate limiting
- Thread-Safe: Seguro para acceso concurrente a través de múltiples goroutines
- Datos Frescos Garantizados: El caché expira automáticamente después de 5 minutos
- Búsquedas Individuales: Obtené tickers específicos sin recuperar colecciones completas
- Operaciones por Lotes: Recuperá eficientemente múltiples valores usando caché compartido
- Pooling de Conexiones: Reutilización automática de conexiones HTTP
- Lógica de Reintentos: Retroceso exponencial incorporado para solicitudes fallidas
- Soporte de Context: Manejo adecuado de cancelación y timeouts
// First call - fetches from API (slow)
start := time.Now()
aapl, _ := client.GetCedear(ctx, "AAPL")
fmt.Printf("First call: %v\n", time.Since(start)) // ~100ms
// Second call - returns from cache (fast!)
start = time.Now()
aapl, _ = client.GetCedear(ctx, "AAPL")
fmt.Printf("Cached call: %v\n", time.Since(start)) // ~50µs (100x faster!)
// Multiple securities use shared cache efficiently
securities, _ := client.GetMultipleSecurities(ctx, []string{"AAPL", "MSFT", "GOOGL"})
// All symbols returned instantly from cache!
// Example: Fetch multiple data types concurrently
var wg sync.WaitGroup
var bluechips []Security
var bonds []Bond
var indices []Index
wg.Add(3)
go func() {
defer wg.Done()
bluechips, _ = client.GetBluechips(ctx) // Cached after first call
}()
go func() {
defer wg.Done()
bonds, _ = client.GetBonds(ctx) // Cached after first call
}()
go func() {
defer wg.Done()
indices, _ = client.GetIndices(ctx) // Cached after first call
}()
wg.Wait()
Esta librería está inspirada en y proporciona funcionalidad equivalente a la librería original en Python pyOBD, con mejoras específicas de Go:
Python pyOBD | Go openbymadata |
---|---|
pandas.DataFrame |
Strongly-typed structs |
No type safety | Compile-time type checking |
GIL limitations | True concurrency |
No built-in retry | Exponential backoff retry |
Basic error handling | Rich error types |
Manual caching | Built-in 5-minute caching |
- Hacé un fork del repositorio
- Creá tu rama de funcionalidad (
git checkout -b feature/funcionalidad-asombrosa
) - Sumá tests para tus cambios
- Corré los tests:
go test ./...
- Commiteá tus cambios (
git commit -am 'Agrega funcionalidad asombrosa'
) - Pusheá a la rama (
git push origin feature/funcionalidad-asombrosa
) - Abrí un Pull Request
Este proyecto está licenciado bajo la Licencia MIT - mirá el archivo LICENSE para más detalles.
- Librería original en Python pyOBD
- BYMA por proporcionar la API gratuita
- Comunidad de Go por excelentes herramientas y librerías
- Lanzamiento inicial
- Cobertura completa de la API de BYMA
- Sistema de caché de 5 minutos incorporado
- Búsquedas individuales de tickers y operaciones por lotes
- Suite completa de tests con servidores HTTP de prueba
- Optimizaciones de rendimiento y manejo rico de errores
- Soporte de context con timeout y cancelación