
Byma
- 199 installs
- 173 repo stars
- Updated June 14, 2026
- gauss314/skills
For development and infrastructure management.
About
byma is an AI coding tool that enhances development workflows. Builders use it for infrastructure, integration, and platform development within the catalog ecosystem.
- byma
- Development
Byma by the numbers
- 199 all-time installs (skills.sh)
- Ranked #2,000 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/gauss314/skills --skill bymaAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 199 |
|---|---|
| repo stars | ★ 173 |
| Last updated | June 14, 2026 |
| Repository | gauss314/skills ↗ |
What it does
For development and infrastructure management.
Files
BYMA — Bolsas y Mercados Argentinos
Skill para extraer datos de mercado de BYMA via su API publica de market data (open.bymadata.com.ar) — sin API key, sin autenticacion.
BYMA es la bolsa principal de Argentina (sucesora del Merval) donde se negocian:
- Acciones lideres (panel de 20 simbolos del MERVAL).
- CEDEARs (~1143 unicos x 2 settlements).
- Bonos publicos soberanos + LECAPs + BONCAPs (~104 unicos x 6 variantes).
- Obligaciones Negociables (ON) corporativas (~2117 items).
- SENEBI ON (segmento bilateral, ~3160 items).
- Cauciones (133 items, formato
DOLAR-DDMM-U-CT-USD). - Opciones (~429 items con strike, OI, vencimiento).
- Indices: S&P MERVAL (
M), BURCAP (G). - Historicos OHLCV diarios/semanales/mensuales para todos los instrumentos.
- Ficha tecnica de bonos (forma de amortizacion, intereses step-up, ISIN, ley aplicable, emisor).
---
⚠️ Aviso Legal
- API publica de BYMA, sin documentacion oficial. Los endpoints pueden cambiar sin aviso.
- Respetar terminos de uso de BYMA. No hacer mas de 1 req/segundo.
- Los datos son delayed (~15 min tipico de mercado argentino).
- Para uso comercial intensivo, contactar BYMA para licencias oficiales.
---
🔒 Nota sobre certificado SSL
BYMA presenta un certificado SSL cuya CA intermedia no esta incluida en el bundle certifi estandar de Python. Esto causa:
SSLError: CERTIFICATE_VERIFY_FAILEDEl script usa `verify=False` — la conexion sigue siendo TLS-encriptada pero se omite la validacion de cadena. Es el patron estandar de las librerias publicas de BYMA (pyhomebroker, bymadata, etc.).
Si preferis no usar verify=False, podes instalar el cert intermedio de BYMA en tu trust store del sistema.
---
Scripts
| Script | Descripcion |
|---|---|
| [fetch_byma.py](./scripts/fetch_byma.py) | Script principal: todos los endpoints disponibles |
---
Uso rapido
# ── PANELES (POST) ────────────────────────────────────────────────────
# Panel lideres: 20 acciones MERVAL x 2 settlements (40 items)
py scripts/fetch_byma.py panel leading-equity
py scripts/fetch_byma.py panel leading-equity --t0 # solo CI (T+0)
py scripts/fetch_byma.py panel leading-equity --t1 # solo 24hs (T+1)
# Panel CEDEARs (~2000 items, lista directa)
py scripts/fetch_byma.py panel cedears
# Panel bonos publicos (1018 items, paginado a 189 por defecto)
py scripts/fetch_byma.py panel public-bonds
py scripts/fetch_byma.py panel public-bonds --all # trae los 1018 en una llamada
# Panel ON corporativas (~2117 items, lista directa)
py scripts/fetch_byma.py panel on
# Panel cauciones (~133 items)
py scripts/fetch_byma.py panel cauciones
# Panel SENEBI ON (3160 items, paginado)
py scripts/fetch_byma.py panel senebi-on
py scripts/fetch_byma.py panel senebi-on --all # trae los 3160 en una llamada
# Panel opciones (~429 items, con strike, OI, vencimiento)
py scripts/fetch_byma.py panel options
# ── HISTORICOS OHLCV (GET) ────────────────────────────────────────────
# Historico de un instrumento — formato simbolo: "TICKER 24HS"
py scripts/fetch_byma.py historico "GGAL 24HS"
py scripts/fetch_byma.py historico "ALUA 24HS"
py scripts/fetch_byma.py historico "AAPL 24HS" # CEDEAR ARS
py scripts/fetch_byma.py historico "AAPLD 24HS" # CEDEAR USD
py scripts/fetch_byma.py historico "AL30 24HS" # Bono ARS
py scripts/fetch_byma.py historico "AL30D 24HS" # Bono USD
py scripts/fetch_byma.py historico "AL30C 24HS" # Bono CCL
py scripts/fetch_byma.py historico "GD30 24HS"
py scripts/fetch_byma.py historico "TZX26 24HS" # BONCAP
py scripts/fetch_byma.py historico "TY30P 24HS" # BONCAP
# Con rango de fechas (default: ultimos 30 dias)
py scripts/fetch_byma.py historico "GGAL 24HS" --desde 2024-05-15 --hasta 2026-06-05
# Resolutions: D (diario), W (semanal), M (mensual)
py scripts/fetch_byma.py historico "GGAL 24HS" --resolution W
py scripts/fetch_byma.py historico "GGAL 24HS" --resolution M
# ── INDICES ────────────────────────────────────────────────────────────
# Historico del S&P MERVAL
py scripts/fetch_byma.py indice M
py scripts/fetch_byma.py indice M --desde 2025-01-01 --hasta 2026-06-05
# Historico del BURCAP
py scripts/fetch_byma.py indice G
# ── FICHA TECNICA DE BONOS ─────────────────────────────────────────────
# Ficha tecnica completa: forma de amortizacion, intereses, ISIN, ley, emisor
py scripts/fetch_byma.py bond-info AE38 # Bono soberano USD 2038 step-up
py scripts/fetch_byma.py bond-info AL30 # Bono soberano USD 2030 ley local
py scripts/fetch_byma.py bond-info GD30 # Bono soberano USD 2030 ley NY
py scripts/fetch_byma.py bond-info AE38C # Variante CCL (misma ficha)
py scripts/fetch_byma.py bond-info AE38D # Variante USD MEP (misma ficha)
py scripts/fetch_byma.py bond-info BPOA7 # BOPREAL Serie 1 A
py scripts/fetch_byma.py bond-info TY30P # BONCAP
py scripts/fetch_byma.py bond-info TZX26 # BONCAP CER
py scripts/fetch_byma.py bond-info S237Q # LECAP
py scripts/fetch_byma.py bond-info SBC1C # ON corporativa
# ── COMBINADO ──────────────────────────────────────────────────────────
# Snapshot de todos los paneles + MERVAL + BURCAP
py scripts/fetch_byma.py all
# ── OUTPUT ─────────────────────────────────────────────────────────────
# Guardar a archivo JSON
py scripts/fetch_byma.py panel leading-equity -o leading.json
py scripts/fetch_byma.py all -o snapshot_byma.json
# Modo silencioso (solo JSON, sin logs)
py scripts/fetch_byma.py panel cauciones -q---
Endpoints disponibles
| Modo | Data | Endpoint |
|---|---|---|
panel leading-equity | Top 20 acciones MERVAL x 2 settlements (40 items) | POST /leading-equity |
panel cedears | CEDEARs (~2000 items) | POST /cedears |
panel public-bonds | Bonos soberanos + LECAPs/BONCAPs (~1018 items) | POST /public-bonds |
panel on | ONs corporativas (~2117 items) | POST /negociable-obligations |
panel cauciones | Cauciones (~133 items) | POST /cauciones |
panel senebi-on | SENEBI ONs (~3160 items, paginado) | POST /senebi-obligaciones-negociables |
panel options | Opciones (~429 items) | POST /options |
historico <SYM> | OHLCV diario/semanal/mensual de un instrumento | GET /chart/historical-series/history?symbol={...} |
indice <COD> | OHLCV de un indice (M=MERVAL, G=BURCAP) | GET /chart/index-historical-series/history?symbol={...} |
bond-info <TICKER> | Ficha tecnica de bono/LECAP/BONCAP/ON (amortizacion, intereses, ISIN, emisor) | POST /bnown/fichatecnica/especies/general |
all | Snapshot de todos los paneles + indices | (combinado) |
Total: 10 endpoints publicos verificados ✅ (8 POST + 2 historicos GET).
Base URL
https://open.bymadata.com.ar/vanoms-be-core/rest/api/bymadata/free---
Convenciones de simbolos
Historicos: formato TICKER 24HS
⚠️ TODOS los historicos requieren el sufijo ` 24HS` (con espacio). Sin sufijo retorna HTTP 400. El sufijo CI tambien retorna 400 (no soportado). 48HS retorna 200 con 0 puntos.
| Tipo | Ejemplo |
|---|---|
| Accion | GGAL 24HS, ALUA 24HS, YPFD 24HS |
| CEDEAR ARS | AAPL 24HS, MSFT 24HS |
| CEDEAR USD | AAPLD 24HS, MSFTD 24HS |
| Bono soberano ARS | AL30 24HS, GD30 24HS, AE38 24HS |
| Bono soberano USD MEP | AL30D 24HS, GD30D 24HS |
| Bono soberano CCL | AL30C 24HS, GD30C 24HS |
| LECAP/BONCAP | TY30P 24HS, TZX26 24HS |
Bonos: convencion de sufijos por moneda
| Sufijo | Variante | Ejemplo |
|---|---|---|
| (sin) | ARS — paridad en pesos | AL30 |
C | CCL (Contado con Liquidacion / EXT) | AL30C |
D | USD MEP | AL30D |
X, Y, Z | otras variantes (intra-day, settlement alt.) | AL30X |
Indices conocidos
| Codigo | Indice |
|---|---|
M | S&P MERVAL |
G | BURCAP |
Otros codigos (A, B, V, etc.) son aceptados pero retornan series con todos ceros — probablemente indices deprecated.
---
Filtros comunes en POST paneles
| Filtro | Descripcion |
|---|---|
T0=true | Solo settlementType=1 (CI / Contado Inmediato) |
T1=true | Solo settlementType=2 (24hs) |
T2=true | Solo settlementType=3 (48hs — practicamente vacio) |
page_size=5000 | Trae todo el dataset en una sola llamada (recomendado para public-bonds y senebi-on) |
⚠️ El parametro page (numero de pagina) es ignorado por la API — siempre devuelve pagina 1. Workaround: usar page_size grande o flag --all.
---
Consideraciones tecnicas
Datos devueltos por panel (todos)
Cada item incluye:
| Campo | Tipo | Descripcion |
|---|---|---|
symbol | string | Ticker BYMA. |
settlementType | string | "1" (CI) o "2" (24hs). |
securityType | string | CS (Common Stock), CD (CEDEAR), GO (Government Obligation), CORP (ON), QS (Caucion), OPT (Option). |
denominationCcy | string | ARS, USD, EXT. |
market | string | BYMA o SENEBI. |
trade | float | Ultimo precio operado. |
closingPrice | float | Cierre del dia. |
settlementPrice | float | Precio de settlement. |
openingPrice, tradingHighPrice, tradingLowPrice | float | OHL del dia. |
previousClosingPrice, previousSettlementPrice | float | Cierre / settlement anterior. |
imbalance | float | Variacion % vs anterior (decimal: -0.0098 = -0.98%). |
volume, tradeVolume | float | Volumen nominal. |
volumeAmount | float | Monto efectivo en moneda. |
vwap | float | Volume-Weighted Average Price. |
bidPrice, offerPrice | float | Mejor bid/offer (0 fuera de horario). |
quantityBid, quantityOffer | float | Cantidades de bid/offer. |
numberOfOrders | int | Numero total de ordenes del dia. |
openInterest | float | Interes abierto (real en opciones/cauciones; 0 en acciones). |
tickDirection | int | -1 / 0 / +1 (downtick / unchanged / uptick). |
tradeHour | string | Hora del ultimo trade. |
Campos extra en bonos / ONs / cauciones / opciones
| Campo | Descripcion |
|---|---|
maturityDate | Fecha de vencimiento (ISO YYYY-MM-DD). |
daysToMaturity | Dias hasta vencimiento. |
underlyingSymbol | Underlying (solo cauciones y opciones). |
optionType | CALL o PUT (solo opciones). |
Datos devueltos por historico e indice
{
"s": "ok",
"t": [unix_seconds, ...],
"o": [opens, ...],
"h": [highs, ...],
"l": [lows, ...],
"c": [closes, ...],
"v": [volumes, ...]
}| Campo | Descripcion |
|---|---|
s | Status: "ok", "no_data", "error". |
t[] | Timestamps unix UTC SECONDS (no millis). |
o[], h[], l[], c[] | OHLC alineados por indice. |
v[] | Volumen (suele ser 0 en indices). |
Datos devueltos por bond-info
Devuelve {content, data, empty, upgrade} donde data[0] (cuando existe) contiene la ficha tecnica del bono. Para acciones, opciones y tickers inexistentes: data: [] y empty: true.
Campos del data[0]:
| Campo | Tipo | Descripcion |
|---|---|---|
ley | string | Jurisdiccion aplicable: Nacional, Extranjera, Nueva York, Inglaterra. Critico para distinguir AL30 (ley local) de GD30 (ley NY). |
formaAmortizacion | string | TEXTO PLANO con el cronograma de amortizacion (numero de cuotas, periodicidad, fechas, %). Para bullet: "Al vencimiento". |
interes | string | TEXTO PLANO con esquema de devengo de intereses. Para step-up describe cada tramo de tasa. Para CER describe el ajuste por inflacion. |
denominacionMinima | int | Denominacion minima de emision. |
fechaEmision | string | YYYY-MM-DD HH:MM:SS.f. |
fechaVencimiento | string | YYYY-MM-DD HH:MM:SS.f. |
fechaDevenganIntereses | string | Fecha inicio devengo (suele estar vacia). |
codigoIsin | string | ISIN del instrumento. |
tipoEspecie | string | Titulos Publicos, Obligaciones Negociables, Letras del Tesoro. |
tipoObligacion | string | Clasificacion regulatoria: Valores Publicos Nacionales, Provinciales, Corporativos. |
tipoGarantia | string | Comun, etc. |
default | string | Estado de default (vacio si esta al dia). |
montoNominal | int | Monto nominal total emitido. |
montoResidual | int | Monto residual actual (post-amortizaciones). |
denominacion | string | Nombre oficial completo del bono. |
insType | string | BOND. |
paisLey | string | Pais de ley aplicable. |
moneda | string | Dolares, Pesos, Pesos Ajustables por CER, Dolar Linked. |
emisor | string | Gobierno Nacional, Provincia de Buenos Aires, YPF S.A., etc. |
Diferencia entre paneles dict y list
| Panel | Tipo response | Estructura |
|---|---|---|
leading-equity, public-bonds, senebi-on | dict | {content: {page_number, page_count, page_size, total_elements_count}, data: [...], empty, upgrade} |
cedears, on, cauciones, options | list | [item, item, ...] directo |
Flags adicionales
| Flag | Descripcion |
|---|---|
--all | Forza page_size=5000 para traer todo en una sola llamada |
--t0 | Solo settlementType=1 (CI) |
--t1 | Solo settlementType=2 (24hs) |
--page N | Numero de pagina (ignorado por la API — usar --all) |
--page-size N | Items por pagina (default: 200) |
--desde YYYY-MM-DD | Fecha desde (historicos) |
--hasta YYYY-MM-DD | Fecha hasta (historicos) |
--resolution X | D, W, M (default: D) |
-o archivo.json | Guardar output a archivo |
-q / --quiet | Modo silencioso (solo JSON) |
Rate limiting
No hay rate limiting documentado. Recomendado:
- Minimo 0.3 segundos entre requests.
- El modo
allusatime.sleep(0.3)automaticamente.
Manejo de errores
| Status | Causas tipicas |
|---|---|
| 400 | Simbolo invalido (sin 24HS, ticker desconocido) |
| 401 | Endpoint inexistente (BYMA usa 401 generico, no 404) |
| 415 | Content-Type erroneo (POST debe ser application/json) |
| 500 | Error interno de BYMA |
Conversion de fechas
from datetime import datetime, timezone
# Unix seconds -> datetime
dt = datetime.fromtimestamp(ts, tz=timezone.utc)
# datetime -> Unix seconds
ts = int(datetime(2026, 6, 5, tzinfo=timezone.utc).timestamp())---
Estructura del skill
skills/byma/
├── SKILL.md # Este archivo (guia rapida)
├── references/
│ └── REFERENCE.md # Documentacion completa de todos los endpoints
└── scripts/
└── fetch_byma.py # Script principal---
Documentacion detallada: Consultar references/REFERENCE.md
para documentacion exhaustiva de cada endpoint, schemas JSON, codigos
de settlementType/securityType, manejo del cert SSL, paginacion y
consideraciones tecnicas.
BYMA — Referencia Completa de la API
BYMA = Bolsas y Mercados Argentinos. Bolsa principal de Argentina —
sucesor del Merval. Negocia acciones, CEDEARs, bonos soberanos y
corporativos (ON), opciones, cauciones y operaciones SENEBI (Sistema
Electronico de Negociacion Bilateral).
>
Esta documentacion cubre la API publica de market data expuesta en
open.bymadata.com.ar (sin API key, sin autenticacion).---
Indice
1. Resumen de endpoints 2. Convenciones de la API 3. Manejo del certificado SSL 4. Panel — Leading Equity 5. Panel — CEDEARs 6. Panel — Public Bonds (Soberanos + LECAPs) 7. Panel — Obligaciones Negociables (ON) 8. Panel — Cauciones 9. Panel — SENEBI Obligaciones Negociables 10. Panel — Opciones 11. Historico — Instrumentos 12. Historico — Indices 13. Bond Info — Ficha tecnica de bonos / ONs 14. Codigos: settlementType, securityType, securitySubType, market 15. Paginacion: limitaciones y workaround 16. Manejo de errores 17. Consideraciones tecnicas
---
1. Resumen de endpoints
| # | Modo CLI | Endpoint | Metodo | Output |
|---|---|---|---|---|
| 1 | panel leading-equity | /leading-equity | POST | dict {content, data[]} 40 items |
| 2 | panel cedears | /cedears | POST | list ~2000 items |
| 3 | panel public-bonds | /public-bonds | POST | dict {content, data[]} 1018 items |
| 4 | panel on | /negociable-obligations | POST | list ~2117 items |
| 5 | panel cauciones | /cauciones | POST | list ~133 items |
| 6 | panel senebi-on | /senebi-obligaciones-negociables | POST | dict {content, data[]} 3160 items |
| 7 | panel options | /options | POST | list ~429 items |
| 8 | historico <SYM> | /chart/historical-series/history?symbol=... | GET | dict {s, t[], o[], h[], l[], c[], v[]} |
| 9 | indice <COD> | /chart/index-historical-series/history?symbol=... | GET | dict {s, t[], o[], h[], l[], c[], v[]} |
| 10 | bond-info <TICKER> | /bnown/fichatecnica/especies/general | POST | dict {content, data[ficha]} |
Total: 10 endpoints publicos verificados ✅ (8 POST + 2 historicos GET).
Base URL
https://open.bymadata.com.ar/vanoms-be-core/rest/api/bymadata/free---
2. Convenciones de la API
Headers
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Accept": "application/json",
"Content-Type": "application/json",
}POST body
Todos los endpoints POST aceptan body JSON. Payload minimo: {}.
Campos opcionales comunes en TODOS los paneles:
| Campo | Tipo | Descripcion |
|---|---|---|
page | int | Numero de pagina, 1-indexed. NOTA: la API la ignora — siempre devuelve pagina 1. Ver seccion 14. |
page_size | int | Items por pagina. Default: 189. Maximo observado: 5000+. |
T0 | bool | Filtra solo settlementType = "1" (CI / Contado Inmediato). |
T1 | bool | Filtra solo settlementType = "2" (24hs). |
T2 | bool | Filtra solo settlementType = "3" (48hs). Devuelve vacio (no se negocia). |
T0 || T1 activan filtros; cuando ambos estan en true o en false, no se filtra.
GET params
Los GET (historicos) usan query string:
| Param | Descripcion |
|---|---|
symbol | Simbolo (formato especifico — ver secciones 11/12). |
resolution | Resolucion: D (diaria), W (semanal), M (mensual). |
from, to | Timestamps Unix en SEGUNDOS (UTC). |
Formato de fechas
- En GET params:
fromytoson unix timestamp en segundos UTC (no milisegundos). - En responses: timestamps unix UTC seconds en
t[]. Fechas ISO enmaturityDate(YYYY-MM-DD).
Conversion
from datetime import datetime, timezone
ts = int(datetime(2026, 6, 5, tzinfo=timezone.utc).timestamp())
# Inverso:
dt = datetime.fromtimestamp(ts, tz=timezone.utc)---
3. Manejo del certificado SSL
BYMA presenta un certificado SSL cuya CA intermedia no esta incluida en los bundles estandar de Python (certifi). Esto causa:
SSLError: CERTIFICATE_VERIFY_FAILED: unable to get local issuer certificateWorkaround usado: verify=False en requests.get/post.
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
r = requests.post(url, json=payload, verify=False)Por que es razonable aqui:
1. La data es publica — no se envian credenciales. 2. La conexion sigue siendo TLS-encrypted (solo se omite la validacion de cadena). 3. Es el patron estandar usado por todas las librerias publicas de BYMA (pyhomebroker, bymadata, etc.). 4. El usuario autorizo explicitamente esta excepcion.
Alternativa mas segura (no usada): instalar el cert intermedio de BYMA en el trust store del sistema. Mas frecuente que falle si BYMA rota el cert.
---
4. Panel — Leading Equity
Endpoint: POST /leading-equity
Panel de 20 acciones lideres del MERVAL × 2 settlements (CI + 24hs) = 40 items.
Body
{} // todos los settlements
{"T0": true} // solo CI (20 items)
{"T1": true} // solo 24hs (20 items)
{"page": 1, "page_size": 100}Response
{
"content": {
"page_number": 1,
"page_count": 1,
"page_size": 189,
"total_elements_count": 40
},
"data": [
{
"tradeVolume": 39310,
"symbol": "ALUA",
"imbalance": -0.0098,
"previousSettlementPrice": 1012,
"offerPrice": 0,
"openInterest": 0,
"vwap": 1018.5664716,
"description": "",
"numberOfOrders": 210,
"openingPrice": 1025,
"tickDirection": 0,
"securityDesc": "",
"securitySubType": "M",
"previousClosingPrice": 1012,
"settlementType": "1",
"quantityOffer": 0,
"tradingHighPrice": 1026,
"denominationCcy": "ARS",
"bidPrice": 0,
"tradingLowPrice": 998,
"market": "BYMA",
"volumeAmount": 40039848,
"volume": 39310,
"trade": 1002,
"tradeHour": "16:35:24",
"securityType": "CS",
"closingPrice": 1002,
"settlementPrice": 1002,
"quantityBid": 0
}
],
"empty": false,
"upgrade": false
}Simbolos del panel (20)
ALUA, BBAR, BMA, BYMA, CEPU, COME, CRES, ECOG, EDN, GGAL, LOMA, METR, PAMP, SUPV, TGNO4, TGSU2, TRAN, TXAR, VALO, YPFD.
Campos
| Campo | Tipo | Descripcion |
|---|---|---|
symbol | string | Ticker BYMA del instrumento. |
settlementType | string | "1" (CI) o "2" (24hs). |
securityType | string | CS (Common Stock). |
securitySubType | string | M (Merval — panel general). |
denominationCcy | string | ARS, USD, EXT. |
market | string | BYMA. |
trade | float | Ultimo precio operado. |
closingPrice | float | Cierre del dia. |
settlementPrice | float | Precio de settlement. |
openingPrice, tradingHighPrice, tradingLowPrice | float | OHL del dia. |
previousClosingPrice | float | Cierre del dia anterior. |
previousSettlementPrice | float | Settlement del dia anterior. |
imbalance | float | Variacion % vs anterior (formato decimal: -0.0098 = -0.98%). |
volume | float | Volumen nominal del dia. |
tradeVolume | float | Volumen ejecutado (puede diferir de volume en algunos casos). |
volumeAmount | float | Monto efectivo en moneda. |
vwap | float | Volume-Weighted Average Price. |
bidPrice, offerPrice | float | Mejor bid/offer actual (0 fuera de horario). |
quantityBid, quantityOffer | float | Cantidades de mejor bid/offer. |
numberOfOrders | int | Numero total de ordenes del dia. |
openInterest | float | Interes abierto (0 en acciones, real en opciones/cauciones). |
tickDirection | int | -1 / 0 / +1 (downtick / unchanged / uptick). |
tradeHour | string | Hora del ultimo trade (HH:MM:SS). |
---
5. Panel — CEDEARs
Endpoint: POST /cedears
CEDEARs (Certificados de Deposito Argentinos) listados en BYMA. ~1143 tickers unicos × 2 settlements = 2000 items.
Body
{} // todos
{"T0": true} // solo CI
{"T1": true} // solo 24hs
{"page_size": 5000} // garantia de traer todoResponse
list directa (no envuelve en {content, data} como leading-equity).
Schema
Mismo schema que leading-equity, excepto:
| Campo | Diferencia |
|---|---|
securityType | CD (CEDEAR). |
securitySubType | (vacio en CEDEARs). |
denominationCcy | ARS, USD, EXT. |
Convencion de tickers
Los CEDEARs tienen variantes por moneda:
| Sufijo | Moneda | Ejemplo |
|---|---|---|
| (sin sufijo) | ARS | AAPL |
C | Caucionable? (CCL?) | AAPLC |
D | USD MEP | AAPLD |
Esto suma 3 tickers x 2 settlements = 6 items por underlying en muchos casos.
---
6. Panel — Public Bonds (Soberanos + LECAPs)
Endpoint: POST /public-bonds
Bonos soberanos nacionales + LECAPs + BONCAPs. ~104 unicos × 6 variantes = 1018 items.
Body
{"page_size": 2000} // recomendado para traer todo
{"T0": true} // solo CI (506 items)
{"T1": true} // solo 24hs (512 items)Response
{
"content": {...},
"data": [
{
"tradeVolume": 5033350,
"symbol": "AE38",
"imbalance": -0.0022,
"previousSettlementPrice": 119400,
"offerPrice": 0,
"openInterest": 0,
"vwap": 119789.7606008,
"description": "",
"numberOfOrders": 1551,
"openingPrice": 119320,
"tickDirection": -1,
"securityDesc": "",
"securitySubType": "B",
"maturityDate": "2038-01-09",
"previousClosingPrice": 119400,
"settlementType": "1",
"quantityOffer": 0,
"tradingHighPrice": 120070,
"denominationCcy": "ARS",
"bidPrice": 0,
"tradingLowPrice": 118850,
"market": "BYMA",
"volumeAmount": 6029437915.2,
"volume": 5033350,
"trade": 119130,
"daysToMaturity": 4237,
"tradeHour": "16:50:01",
"securityType": "GO",
"closingPrice": 119130,
"settlementPrice": 119130,
"quantityBid": 0
}
]
}Campos adicionales vs acciones
| Campo | Descripcion |
|---|---|
maturityDate | Fecha de vencimiento del bono (ISO YYYY-MM-DD). |
daysToMaturity | Dias hasta vencimiento. |
securityType | GO (Government Obligation). |
securitySubType | B (Bond) — comun en todos. |
denominationCcy | ARS, USD, EXT. |
Convencion de tickers — bonos hard dollar
| Sufijo | Variante | Ejemplo |
|---|---|---|
| (sin) | ARS (paridad en pesos) | AL30, GD30, AE38 |
C | EXT (CCL) | AL30C |
D | USD MEP | AL30D |
X, Y, Z | otras variantes (intra-day, settlements alternativos) | AL30X |
LECAPs y BONCAPs
Identificables por prefijo:
S*(5 chars): LECAPs — ejS237Q,SA24D,SBC1CT*(5 chars): BONCAPs — ejT30A7,T15E7,T2X7
No todos los simbolos LECAP/BONCAP tienen historico disponible. Algunos
antiguos (S31E6) retornan 0 puntos.
---
7. Panel — Obligaciones Negociables (ON)
Endpoint: POST /negociable-obligations
Obligaciones Negociables corporativas (bonos corporativos). ~2117 items.
Body
{}
{"page_size": 5000}Response
list directa (no envuelve).
Campos especificos
securityType=CORPsecuritySubType= (vacio oB)- Misma estructura que public-bonds (incluye
maturityDate,daysToMaturity).
Convencion de tickers
- Acortados a ~5 chars con letras de variante (D, C, O, X, etc.)
- Ejemplos:
SBC1C,T641D,T661O
---
8. Panel — Cauciones
Endpoint: POST /cauciones
Cauciones (prestamos colateralizados de muy corto plazo) y operaciones a plazo. ~133 items.
Body
{}Response
list directa.
Schema
{
"tradeVolume": 0.0,
"symbol": "DOLAR-0107-U-CT-USD",
"imbalance": 0.0,
"previousSettlementPrice": 0.03,
"offerPrice": 0.0,
"openInterest": 0.0,
"vwap": 0.0,
"description": "",
"numberOfOrders": 0,
"openingPrice": 0.0,
"tickDirection": -1,
"underlyingSymbol": "DOLAR",
"securityDesc": "",
"securitySubType": "",
"maturityDate": "2026-07-01",
"previousClosingPrice": 0.03,
"settlementType": "1",
"quantityOffer": 0.0,
"tradingHighPrice": 0.0,
"denominationCcy": "USD",
"bidPrice": 0.0,
"tradingLowPrice": 0.0,
"market": "BYMA",
"volumeAmount": 0.0,
"volume": 0.0,
"trade": 0.0,
"daysToMaturity": 27,
"securityType": "QS",
"closingPrice": 0.03,
"settlementPrice": 0,
"quantityBid": 0.0
}Convencion de tickers
{UNDERLYING}-{DDMM}-U-CT-{CCY} — ej DOLAR-0107-U-CT-USD:
DOLAR= activo subyacente.0107= vencimiento (1 de Julio).U-CT= identificador del tipo.USD= moneda.
Campos especificos
underlyingSymbol= activo subyacente (DOLAR).securityType=QS(Caucion).maturityDate+daysToMaturity= vencimiento.- La cotizacion (
trade,closingPrice, etc.) esta en formato de tasa o
precio segun el instrumento (cauciones suelen cotizar en tasa o factor).
---
9. Panel — SENEBI Obligaciones Negociables
Endpoint: POST /senebi-obligaciones-negociables
ONs negociadas en el segmento SENEBI (Sistema Electronico de Negociacion Bilateral) — operaciones bilaterales reportadas a BYMA. ~3160 items.
Body
{"page_size": 5000} // recomendado
{"T0": true} // solo CI (1505 items)
{"T1": true} // solo 24hs (1655 items)Response
Envuelve en {content, data} igual que leading-equity.
Schema
{
"symbol": "A11LD.SB",
"tradeVolume": 0,
"imbalance": 0,
"previousSettlementPrice": 0,
"offerPrice": 0,
"vwap": 0,
"description": "",
"numberOfOrders": 0,
"openingPrice": 0,
"tickDirection": 0,
"securityDesc": "",
"securitySubType": "",
"maturityDate": "2028-03-31",
"previousClosingPrice": 0,
"settlementType": "1",
"quantityOffer": 0,
"tradingHighPrice": 0,
"denominationCcy": "EXT",
"bidPrice": 0,
"tradingLowPrice": 0,
"market": "SENEBI",
"volumeAmount": 0,
"volume": 0,
"trade": 0,
"daysToMaturity": 666,
"securityType": "CORP",
"closingPrice": 0,
"settlementPrice": 0,
"quantityBid": 0
}Diferencias vs panel on
market=SENEBI(en vez deBYMA).- Sufijo
.SBen elsymbol(ejA11LD.SB). - Mucho mas volumen de tickers porque SENEBI agrupa toda emision corporativa
bilateral, no solo las listadas en panel principal.
---
10. Panel — Opciones
Endpoint: POST /options
Opciones de acciones argentinas. ~429 items.
Body
{}Response
list directa.
Schema
{
"tradeVolume": 1.0,
"symbol": "ALUC1000AG",
"imbalance": 0.0,
"previousSettlementPrice": 0.0,
"offerPrice": 0.0,
"openInterest": 0.0,
"vwap": 65.0,
"description": "",
"numberOfOrders": 1,
"openingPrice": 65.0,
"optionType": "CALL",
"tickDirection": 0,
"underlyingSymbol": "ALUA",
"securityDesc": "",
"securitySubType": "",
"maturityDate": "2026-08-21",
"previousClosingPrice": 0.0,
"settlementType": "2",
"quantityOffer": 0.0,
"tradingHighPrice": 65.0,
"denominationCcy": "ARS",
"bidPrice": 0.0,
"tradingLowPrice": 65.0,
"market": "BYMA",
"volumeAmount": 6500.0,
"volume": 1.0,
"trade": 65.0,
"daysToMaturity": 78,
"tradeHour": "14:59:50",
"securityType": "OPT",
"closingPrice": 65.0,
"settlementPrice": 65.0,
"quantityBid": 0.0
}Campos especificos
| Campo | Descripcion |
|---|---|
optionType | CALL o PUT. |
underlyingSymbol | Activo subyacente (ALUA, GGAL, etc.). |
securityType | OPT. |
maturityDate | Vencimiento de la opcion. |
openInterest | Interes abierto (real, no 0 como en acciones). |
Decodificacion del ticker
Las opciones BYMA siguen el formato: {ROOT}{C|V}{STRIKE}{MES}{AÑO?}
ALUC1000AG → ALUA + C (Call) + 1000 (strike) + AG (Agosto)
Para parsear consistentemente, usar el campo strike cuando estepresente, o derivarlo de underlyingSymbol + posicion del strike.El esquema oficial requiere decodificar por contexto.
---
11. Historico — Instrumentos
Endpoint: GET /chart/historical-series/history
OHLCV historico de un instrumento (accion, CEDEAR, bono, ON, opcion).
Query params
| Param | Descripcion |
|---|---|
symbol | Formato: `{TICKER} 24HS`. Ejemplo: GGAL 24HS. |
resolution | D (diaria), W (semanal), M (mensual). |
from, to | Unix timestamp en segundos UTC. |
Formato simbolo
| Tipo de instrumento | Formato | Ejemplo |
|---|---|---|
| Accion ARS | TICKER 24HS | GGAL 24HS |
| Accion USD MEP | TICKERD 24HS | (raro) |
| CEDEAR ARS | TICKER 24HS | AAPL 24HS |
| CEDEAR USD | TICKERD 24HS | AAPLD 24HS |
| Bono soberano ARS | TICKER 24HS | AL30 24HS |
| Bono soberano USD | TICKERD 24HS | AL30D 24HS |
| Bono soberano CCL | TICKERC 24HS | AL30C 24HS |
| LECAP/BONCAP | TICKER 24HS | TY30P 24HS, TZX26 24HS |
| Opcion | OPTSYMBOL 24HS | ALUC1000AG 24HS (suele estar vacio) |
⚠️ Sufijo CI no funciona en historicos — retorna HTTP 400.
⚠️ 48HS funciona pero retorna 0 puntos (no se negocia ese settlement con regularidad).
⚠️ Sin sufijo retorna 400 — siempre incluir 24HS.Response
{
"s": "ok",
"t": [1715569200, 1715655600, 1715742000, ...],
"o": [3500.0, 3520.5, 3490.0, ...],
"h": [3550.0, 3540.0, 3510.0, ...],
"l": [3480.0, 3490.0, 3460.0, ...],
"c": [3520.0, 3510.0, 3495.0, ...],
"v": [50000, 65000, 42000, ...]
}Campos
| Campo | Descripcion |
|---|---|
s | Status: "ok", "no_data", "error". |
t[] | Timestamps unix UTC seconds (alineados por indice con OHLCV). |
o[] | Open. |
h[] | High. |
l[] | Low. |
c[] | Close. |
v[] | Volume. |
Comportamiento de resolution
| Resolution | Comportamiento |
|---|---|
D | Diario — funciona como esperado. |
W | Semanal — agrega 5 dias en 1 bar. |
M | Mensual — agrega ~22 dias en 1 bar. |
1, 5, 15, 60, 240 | La API acepta pero retorna el mismo set que D (intraday no expuesto). |
---
12. Historico — Indices
Endpoint: GET /chart/index-historical-series/history
Serie historica de un indice BYMA.
Query params
Igual que historico de instrumentos:
| Param | Descripcion |
|---|---|
symbol | Codigo de letra del indice (ej: M, G). |
resolution | D (la API ignora este parametro en indices). |
from, to | Unix timestamp seconds UTC. |
Indices verificados con datos
| Codigo | Indice | Rango tipico (Jun 2026) |
|---|---|---|
M | S&P MERVAL | 2.3M - 3.2M |
G | BURCAP | 100M - 137M |
Indices que existen pero retornan ceros
A, B, V y otras letras retornan HTTP 200 con c[] lleno de 0.0 — probablemente indices deprecated o sin publicacion historica oficial.
Response
Mismo schema que historico de instrumentos:
{
"s": "ok",
"t": [1715569200, ...],
"o": [...], "h": [...], "l": [...], "c": [...], "v": [...]
}⚠️ El campo v[] (volumen) tipicamente es 0 en indices.---
13. Bond Info — Ficha tecnica de bonos / ONs
Endpoint: POST /bnown/fichatecnica/especies/general
Ficha tecnica completa de un bono, LECAP, BONCAP u ON: ley aplicable, forma de amortizacion, esquema de intereses (cupones), fechas de emision/vencimiento, ISIN, moneda, monto nominal/residual, emisor.
Es el endpoint principal para calculos de cashflow porque devuelve el texto oficial con el cronograma de amortizacion y la formula de intereses (incluido step-up para bonos con tasas crecientes).
Body
{"symbol": "AE38"}| Campo | Tipo | Descripcion |
|---|---|---|
symbol | string | Ticker SIN sufijo de settlement. Ej: AE38, AL30, GD30, BPOA7, TY30P, S237Q, SBC1C. Tambien acepta variantes por moneda: AE38C, AE38D. |
⚠️ Payload vacio ({}) retorna 200 condata: []yempty: true.
Payload null retorna 400 ("Failed to read request").Response
{
"content": {
"page_number": 1,
"page_count": 1,
"page_size": 50,
"total_elements_count": 1
},
"data": [
{
"ley": "Nacional",
"formaAmortizacion": "La amortizacion se efectuara en VEINTIDOS (22) cuotas semestrales iguales el 9 de enero y el 9 de julio de cada año, con la primera cuota el 9 de julio de 2027 y la ultima cuota el 9 de enero de 2038.\nLa totalidad de las condiciones definitivas de la presente emision constan en la Resolucion N° 381/2020 del Ministerio de Economia de la Nacion publicada el 18.08.2020 en el Boletin Oficial.",
"denominacionMinima": 1,
"fechaVencimiento": "2038-01-09 00:00:00.0",
"tipoGarantia": "Comun",
"fechaEmision": "2020-09-04 00:00:00.0",
"fechaDevenganIntereses": "",
"codigoIsin": "ARARGE3209U2",
"tipoEspecie": "Titulos Publicos",
"default": "",
"tipoObligacion": "Valores Publicos Nacionales",
"montoNominal": 10063292009,
"denominacion": "BONOS DE LA REPUBLICA ARGENTINA EN DOLARES ESTADOUNIDENSES STEP UP 2038",
"insType": "BOND",
"paisLey": "",
"moneda": "Dolares",
"montoResidual": 10063292009,
"interes": "Devengaran intereses, sobre la base de un año de 360 dias integrado por 12 meses de 30 dias cada uno, de acuerdo con las siguientes tasas anuales:\ni. Del 4 de septiembre de 2020 (inclusive) al 9 de julio de 2021 (exclusive): 0,125%.\nii. Del 9 de julio de 2021 (inclusive) al 9 de julio de 2022 (exclusive): 2,00%.\niii. Del 9 de julio de 2022 (inclusive) al 9 de julio de 2023 (exclusive): 3,875%.\niv. Del 9 de julio de 2023 (inclusive) al 9 de julio de 2024 (exclusive): 4,25%.\nv. Del 9 de julio de 2024 (inclusive) al vencimiento: 5,00%.",
"emisor": "Gobierno Nacional"
}
],
"empty": false,
"upgrade": false
}Campos de data[0]
| Campo | Tipo | Descripcion |
|---|---|---|
ley | string | Jurisdiccion aplicable: Nacional, Extranjera, Nueva York, Inglaterra. Critico para distinguir AL30 (ley local) de GD30 (ley NY). |
formaAmortizacion | string | TEXTO PLANO con el cronograma de amortizacion. Tipicamente especifica numero de cuotas, periodicidad (semestral/trimestral), fechas exactas y monto/proporcion por cuota. Para bullet: "Al vencimiento". |
denominacionMinima | int | Denominacion minima de emision (ej: 1 = 1 unidad, 100 = laminas de $100). |
fechaVencimiento | string | Fecha de vencimiento en formato YYYY-MM-DD HH:MM:SS.f. |
tipoGarantia | string | Tipo de garantia: Comun, Con Garantia Especifica, etc. |
fechaEmision | string | Fecha de emision del bono. |
fechaDevenganIntereses | string | Fecha de inicio del devengo de intereses (suele estar vacia si coincide con emision). |
codigoIsin | string | Codigo ISIN (International Securities Identification Number). |
tipoEspecie | string | Titulos Publicos, Obligaciones Negociables, Letras del Tesoro. |
default | string | Estado de default (vacio si esta al dia). |
tipoObligacion | string | Clasificacion regulatoria: Valores Publicos Nacionales, Provinciales, Corporativos. |
montoNominal | int | Monto nominal total emitido (en unidades de la moneda). |
denominacion | string | Nombre oficial completo del bono. |
insType | string | BOND (siempre). |
paisLey | string | Pais de la ley aplicable (texto libre, puede estar vacio). |
moneda | string | Moneda en texto: Dolares, Pesos, Pesos Ajustables por CER, Dolar Linked. |
montoResidual | int | Monto residual actual (post-amortizaciones). |
interes | string | TEXTO PLANO con esquema de devengo de intereses. Para step-up describe cada tramo de tasa. Para tasa fija da el valor. Para CER/Dolar-linked describe el indice ajuste. |
emisor | string | Emisor: Gobierno Nacional, Provincia de Buenos Aires, YPF S.A., etc. |
Ejemplos de aplicacion
1. Distinguir AL30 (ley local) vs GD30 (ley NY):
al30 = fetch_bond_info("AL30")
gd30 = fetch_bond_info("GD30")
print(al30['data'][0]['ley']) # "Nacional"
print(gd30['data'][0]['ley']) # "Nueva York" (mas seguro juridicamente)2. Parsear cronograma de amortizacion (AE38):
info = fetch_bond_info("AE38")
texto = info['data'][0]['formaAmortizacion']
# "22 cuotas semestrales iguales el 9 de enero y el 9 de julio,
# primera 9 julio 2027, ultima 9 enero 2038"
# -> ~4.545% del nominal por cuota, 22 cuotas3. Detectar step-up vs tasa fija:
info = fetch_bond_info("AE38")
if "tasas anuales" in info['data'][0]['interes'].lower():
print("Step-up bond")Variantes y limitaciones
| Caso | Comportamiento |
|---|---|
| Ticker valido (bono/ON/LECAP) | 200 con ficha completa |
Variante por moneda (AE38C, AE38D) | 200 con misma ficha (datos de emisor) |
Accion (GGAL, AAPL) | 200 con data: [] (vacio) |
| Opcion / caucion | 200 con data: [] (vacio) |
| Ticker inexistente | 200 con data: [] |
Payload vacio {} | 200 con data: [] y empty: true |
Payload null | 400 "Failed to read request" |
Encoding
Los textos largos (formaAmortizacion, interes) pueden contener caracteres latin-1 que se muestran como ? en consolas Windows pero se salvan correctamente con json.dumps(..., ensure_ascii=False) a archivos UTF-8.
---
14. Codigos: settlementType, securityType, securitySubType, market
settlementType
| Valor | Significado |
|---|---|
"1" | CI (Contado Inmediato — T+0) |
"2" | 24hs (T+1) |
"3" | 48hs (T+2) — practicamente no se usa hoy |
securityType
| Codigo | Tipo | Aparece en |
|---|---|---|
CS | Common Stock | leading-equity |
CD | CEDEAR | cedears |
GO | Government Obligation (bono soberano) | public-bonds |
CORP | Corporate (ON) | negociable-obligations, senebi-obligaciones-negociables |
QS | Caucion / Repo | cauciones |
OPT | Option | options |
securitySubType
| Codigo | Significado | Aparece en |
|---|---|---|
M | Merval (panel general) | leading-equity |
B | Bond | public-bonds |
"" | (vacio) | cedears, on, options, cauciones, senebi |
market
| Codigo | Significado |
|---|---|
BYMA | Mercado principal BYMA |
SENEBI | Sistema Electronico de Negociacion Bilateral |
denominationCcy
| Codigo | Moneda |
|---|---|
ARS | Pesos argentinos |
USD | Dolar estadounidense (MEP) |
EXT | EXTerior / CCL (Contado con Liquidacion) |
tickDirection
| Valor | Significado |
|---|---|
-1 | Down-tick (precio bajo vs trade anterior) |
0 | Sin cambio (o sin actividad) |
+1 | Up-tick (precio subio vs trade anterior) |
---
15. Paginacion: limitaciones y workaround
Problema
Los endpoints POST devuelven en el content un campo page_count que sugiere paginacion (ej: page_count: 6 para public-bonds). Sin embargo, el parametro `page` en el body es IGNORADO por la API actual.
Evidencia experimental:
# Todas estas variantes retornan SIEMPRE pagina 1:
post("public-bonds", {"page": 2, "page_size": 10})
post("public-bonds", {"page_number": 2, "page_size": 10})
post("public-bonds", {"pageNumber": 2, "pageSize": 10})
post("public-bonds", {"current_page": 2})
post("public-bonds", {"offset": 10, "limit": 10})
# El response siempre tiene content.page_number == 1, data[0].symbol == "AE38"Tampoco funciona:
Content-Type: application/x-www-form-urlencoded(415 Unsupported)- Headers extra (
Origin,Referer,X-Requested-With) - camelCase de los params
Workaround
Usar page_size grande para traer todo el dataset en una sola llamada:
post("public-bonds", {"page_size": 2000}) # 1018 items en 1 call
post("senebi-obligaciones-negociables", {"page_size": 5000}) # 3160 itemsEl script fetch_byma.py expone esto via flag --all que setea page_size=5000 automaticamente.
Tabla por panel
| Panel | Total items observado | Pagination util? |
|---|---|---|
leading-equity | 40 | No (cabe en defaults) |
cedears | 2000 | No (devuelve list directa, sin pagination) |
public-bonds | 1018 | Page IGNORADO. Usar page_size=2000 |
negociable-obligations | 2117 | No (devuelve list directa) |
cauciones | 133 | No |
senebi-obligaciones-negociables | 3160 | Page IGNORADO. Usar page_size=5000 |
options | 429 | No |
---
16. Manejo de errores
| Status | Causas tipicas |
|---|---|
| 200 | OK — verificar response.s == "ok" en historicos. |
| 400 | Simbolo invalido en historico, sin sufijo 24HS, o param requerido faltante. |
| 401 | Endpoint inexistente (BYMA usa 401 generico, no 404). |
| 415 | Content-Type erroneo (POST debe ser application/json). |
| 500 | Error interno de BYMA. |
Patrones de error en historicos
symbol=GGAL(sin sufijo) → 400 (body vacio).symbol=GGAL CI(sufijo CI no soportado) → 400.symbol=GGAL 48HS→ 200 con t=[].symbol=AAPL 24HS(CEDEAR valido) → 200 con datos.
Paths que retornan 401
Cualquier path no incluido en la lista oficial:
/indices,/indexes,/symbols,/search,/leading-bonds, etc.
---
17. Consideraciones tecnicas
Rate limiting
No documentado ni observado limite. Se recomienda:
- Minimo 0.3 segundos entre requests.
- El
allmode usatime.sleep(0.3)entre cada llamada. - Para batches > 50 requests, considerar pool con
aiohttpcon
concurrency cap = 5.
Delay de los datos
- Paneles intradia: tiempo real (15-min delay tipico de mercado argentino).
- Historicos: T-1 disponible al cierre del dia siguiente (~19hs ART).
Horarios de mercado
- Rueda BYMA: 11:00 - 17:00 ART (Lunes a Viernes).
- Pre-mercado / Post-mercado: limitado, mayormente no operativo.
Encoding
API retorna UTF-8 valido. No hay problemas de encoding como en MAE.
CORS
API admite CORS para localhost y dominios oficiales de BYMA. Para uso desde frontend, considerar proxy de cache.
Disponibilidad
- API disponible 24/7.
- Datos se actualizan solo en horario de rueda.
- Fines de semana y feriados: snapshots devuelven datos del ultimo dia habil.
Aviso legal
- API publica de BYMA, sin documentacion oficial.
- Los endpoints pueden cambiar sin aviso.
- Para uso comercial intensivo, contactar BYMA para licencias oficiales.
---
Referencias
- BYMA Oficial: https://www.byma.com.ar
- Open Market Data: https://open.bymadata.com.ar
- CNV (regulador): https://www.cnv.gov.ar
- Listado oficial de simbolos: ver paneles via API
"""
BYMA Data Fetcher — Bolsas y Mercados Argentinos (open.bymadata.com.ar).
API publica de market data de BYMA. Sin API key, sin autenticacion.
SSL: el cert SSL de BYMA no es validable por bundles standard de Python,
por lo que se usa verify=False (ver SKILL.md). La data es publica.
Endpoints disponibles:
PANELES (POST):
- panel leading-equity Panel lideres: 20 acciones x 2 settlements (40 items)
- panel cedears CEDEARs (~1143 unicos, 2000 items con settlement)
- panel public-bonds Bonos publicos soberanos + LECAPs/BONCAPs (1018 items)
- panel on Obligaciones negociables corporativas (2117 items)
- panel cauciones Cauciones por fecha+plazo (133 items)
- panel senebi-on ON segmento SENEBI (3160 items, paginado)
- panel options Opciones (429 items, con strike, OI, etc.)
HISTORICOS (GET):
- historico <SYM> Historico OHLCV diario de un instrumento
Formato simbolo: "TICKER 24HS" (ej: "GGAL 24HS")
Bonds USD: "AL30D 24HS"; CCL: "AL30C 24HS"
- indice <COD> Historico de un indice de BYMA (M=MERVAL, G=BURCAP)
FICHA TECNICA (POST):
- bond-info <TICKER> Ficha tecnica de un bono/LECAP/BONCAP/ON:
forma de amortizacion, intereses, ISIN, ley,
emisor, fechas, monto nominal/residual, etc.
Uso:
py fetch_byma.py panel leading-equity
py fetch_byma.py panel leading-equity --t0 # solo CI (settlementType=1)
py fetch_byma.py panel leading-equity --t1 # solo 24hs (settlementType=2)
py fetch_byma.py panel cedears
py fetch_byma.py panel public-bonds # paginado total 1018
py fetch_byma.py panel public-bonds --all # trae todos en una llamada
py fetch_byma.py panel on
py fetch_byma.py panel cauciones
py fetch_byma.py panel senebi-on
py fetch_byma.py panel options
py fetch_byma.py historico "GGAL 24HS"
py fetch_byma.py historico "AL30 24HS"
py fetch_byma.py historico "AL30D 24HS" --desde 2024-05-15 --hasta 2026-06-05
py fetch_byma.py historico "AAPL 24HS"
py fetch_byma.py indice M # MERVAL
py fetch_byma.py indice G # BURCAP
py fetch_byma.py indice M --desde 2025-01-01 --hasta 2026-06-05
py fetch_byma.py bond-info AE38 # Ficha tecnica AE38
py fetch_byma.py bond-info AL30 # Ficha tecnica AL30
py fetch_byma.py bond-info TY30P # Ficha tecnica BONCAP TY30P
py fetch_byma.py all # snapshot todos los paneles
"""
from __future__ import annotations
import argparse
import json
import logging
import sys
import time
from datetime import datetime, timezone
from typing import Any
import requests
import urllib3
# BYMA usa cert SSL no validable por bundles standard de Python.
# La data es publica, sin credenciales. Disable warnings (autorizado).
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
log = logging.getLogger("byma")
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
datefmt="%H:%M:%S",
)
BASE = "https://open.bymadata.com.ar/vanoms-be-core/rest/api/bymadata/free"
HEADERS = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
),
"Accept": "application/json",
"Content-Type": "application/json",
}
# ── Constantes ─────────────────────────────────────────────────────────────
# Paneles soportados (POST). Key = nombre interno usado en CLI, value = path API.
PANELS = {
"leading-equity": "leading-equity",
"cedears": "cedears",
"public-bonds": "public-bonds",
"on": "negociable-obligations",
"cauciones": "cauciones",
"senebi-on": "senebi-obligaciones-negociables",
"options": "options",
}
# Paneles que devuelven `{content, data, ...}` (paginados).
# El resto devuelve una lista directa.
PAGED_PANELS = {"leading-equity", "public-bonds", "senebi-on"}
# Indices verificados con datos consistentes:
# M = MERVAL (~3.0-3.2M actual)
# G = BURCAP (~135M actual)
# Otros codigos (A, B, V) son aceptados pero devuelven todos ceros.
INDICES_CONOCIDOS = {
"M": "S&P MERVAL",
"G": "BURCAP",
}
# Resoluciones soportadas. Para indices, todas devuelven el mismo dataset
# (resolution parece ignorado en index-historical-series).
# Para historical-series de instrumentos: D, W, M tienen efecto real.
RESOLUTIONS = ["D", "W", "M"]
# ── HTTP helpers ───────────────────────────────────────────────────────────
def _post(path: str, payload: dict | None = None) -> Any:
"""POST request. BYMA usa verify=False por su cert SSL no estandar."""
r = requests.post(
f"{BASE}/{path}",
headers=HEADERS,
json=payload or {},
timeout=30,
verify=False,
)
r.raise_for_status()
return r.json()
def _get(path: str, params: dict) -> Any:
"""GET request con verify=False."""
r = requests.get(
f"{BASE}/{path}",
headers=HEADERS,
params=params,
timeout=30,
verify=False,
)
r.raise_for_status()
return r.json()
def _date_to_unix(date_str: str | None, default_days_ago: int = 30) -> int:
"""Convierte 'YYYY-MM-DD' a unix timestamp (segundos UTC)."""
if date_str:
dt = datetime.strptime(date_str, "%Y-%m-%d").replace(tzinfo=timezone.utc)
return int(dt.timestamp())
return int(time.time()) - default_days_ago * 86400
# ── Paneles ────────────────────────────────────────────────────────────────
def fetch_panel(
panel: str,
page: int = 1,
page_size: int = 200,
t0: bool = False,
t1: bool = False,
fetch_all: bool = False,
) -> Any:
"""Fetch generico de paneles (POST endpoints).
Args:
panel: nombre interno del panel (ver PANELS dict).
page: numero de pagina (1-indexed). NOTA: la API ignora este parametro
en la version actual — siempre retorna pagina 1. Workaround: usar
`fetch_all=True` o `page_size` grande.
page_size: items por pagina. Default 200. Maximo observado: 5000+.
t0: si True, filtra solo settlementType=1 (CI).
t1: si True, filtra solo settlementType=2 (24hs).
fetch_all: si True, fuerza page_size=5000 para traer todo en una sola llamada.
Returns:
Para PAGED_PANELS: dict con keys `content`, `data`, `empty`, `upgrade`.
Para el resto: list directa de items.
"""
if panel not in PANELS:
raise ValueError(f"Panel invalido. Validos: {list(PANELS)}")
path = PANELS[panel]
payload: dict[str, Any] = {}
if fetch_all:
payload["page_size"] = 5000
else:
payload["page"] = page
payload["page_size"] = page_size
if t0:
payload["T0"] = True
if t1:
payload["T1"] = True
return _post(path, payload)
# ── Historicos ─────────────────────────────────────────────────────────────
def fetch_historico(
symbol: str,
desde: str | None = None,
hasta: str | None = None,
resolution: str = "D",
) -> dict:
"""Historico OHLCV diario/semanal/mensual de un instrumento.
Formato del simbolo: `{TICKER} 24HS`. Ejemplos validos:
"GGAL 24HS" — acciones
"AAPL 24HS" — CEDEARs ARS
"AAPLD 24HS" — CEDEARs USD
"AL30 24HS" — bonos ARS
"AL30D 24HS" — bonos USD
"AL30C 24HS" — bonos CCL
"TY30P 24HS" — LECAPs/BONCAPs
NOTA: el sufijo "CI" no funciona en historicos (retorna 400). Solo 24HS.
Cualquier ticker sin sufijo retorna 400.
Args:
symbol: simbolo completo con " 24HS".
desde: fecha desde YYYY-MM-DD (default: 30 dias atras).
hasta: fecha hasta YYYY-MM-DD (default: hoy).
resolution: D (diario), W (semanal), M (mensual). Default D.
Returns:
dict con keys `s` (status), `t[]` (timestamps unix), `o[]`, `h[]`,
`l[]`, `c[]`, `v[]` (OHLCV arrays sincronizados por indice).
"""
if resolution not in RESOLUTIONS:
log.warning(f"Resolution {resolution!r} no estandar; pueden esperarse resultados extraños")
from_ts = _date_to_unix(desde, default_days_ago=30)
to_ts = _date_to_unix(hasta, default_days_ago=0)
return _get("chart/historical-series/history", {
"symbol": symbol,
"resolution": resolution,
"from": from_ts,
"to": to_ts,
})
def fetch_indice(
symbol: str,
desde: str | None = None,
hasta: str | None = None,
resolution: str = "D",
) -> dict:
"""Historico de un indice BYMA.
Indices verificados con datos:
M = S&P MERVAL
G = BURCAP
Otros codigos (A, B, V, etc.) son aceptados por la API pero retornan
series con todos ceros — probablemente indices deprecated o sin
publicacion historica.
Args:
symbol: codigo de letra del indice (M, G, etc.).
desde, hasta: rango YYYY-MM-DD (default: ultimos 30 dias).
resolution: D/W/M (default D). NOTA: en indices la API ignora este
parametro y siempre devuelve diario.
Returns:
dict con la misma estructura que `fetch_historico`.
"""
from_ts = _date_to_unix(desde, default_days_ago=30)
to_ts = _date_to_unix(hasta, default_days_ago=0)
return _get("chart/index-historical-series/history", {
"symbol": symbol,
"resolution": resolution,
"from": from_ts,
"to": to_ts,
})
# ── Ficha tecnica de bonos / ONs ───────────────────────────────────────────
def fetch_bond_info(symbol: str) -> dict:
"""Ficha tecnica de un bono / LECAP / BONCAP / ON.
Devuelve TODA la info estatica del instrumento: ley aplicable, forma
de amortizacion (texto), fechas de emision/vencimiento, ISIN, moneda,
monto nominal/residual, descripcion de intereses, emisor, tipo de
garantia, denominacion minima.
El campo mas importante para finanzas es **`formaAmortizacion`**, que
describe en texto plano el cronograma de amortizacion (ej: "22 cuotas
semestrales iguales el 9 de enero y el 9 de julio de cada año desde
julio 2027 hasta enero 2038"). `interes` describe el esquema de cupones
(paso a paso para step-up).
Args:
symbol: ticker del bono SIN sufijo de settlement.
Ejemplos: "AE38", "AL30", "GD30", "AE38C", "AE38D",
"BPOA7", "TY30P", "TZX26", "S237Q", "SBC1C".
Tambien funciona con variantes por moneda (C, D).
Para acciones devuelve data vacia.
Returns:
dict con keys:
- `content`: pagination (page_number, page_count, page_size, total_elements_count)
- `data[0]`: ficha tecnica con keys:
- `ley`: jurisdiccion (Nacional, Extranjera, etc.)
- `formaAmortizacion`: TEXTO con cronograma de amortizacion
- `denominacionMinima`: denominacion minima de emision
- `fechaVencimiento`: ISO datetime
- `tipoGarantia`: Comun, etc.
- `fechaEmision`: ISO datetime
- `fechaDevenganIntereses`: fecha inicio devengo
- `codigoIsin`: codigo ISIN
- `tipoEspecie`: Titulos Publicos, etc.
- `default`: estado de default
- `tipoObligacion`: clasificacion regulatoria
- `montoNominal`: monto nominal emitido
- `denominacion`: nombre oficial completo
- `insType`: BOND
- `paisLey`: pais de la ley aplicable
- `moneda`: Dolares, Pesos, etc.
- `montoResidual`: monto residual actual
- `interes`: TEXTO con esquema de cupones
- `emisor`: emisor (Gobierno Nacional, Provincia, Corporativo)
- `empty`: bool
"""
return _post("bnown/fichatecnica/especies/general", {"symbol": symbol})
# ── Mode ALL ───────────────────────────────────────────────────────────────
def fetch_all() -> dict:
"""Snapshot de TODOS los paneles + indice MERVAL + BURCAP."""
log.info("Fetching ALL BYMA snapshots...")
result: dict[str, Any] = {"timestamp": datetime.now().isoformat()}
for name in PANELS:
try:
log.info(f" Panel {name}...")
result[f"panel_{name}"] = fetch_panel(name, fetch_all=True)
time.sleep(0.3)
except Exception as e:
log.warning(f" {name}: {e}")
result[f"panel_{name}"] = {"error": str(e)}
for code in INDICES_CONOCIDOS:
try:
log.info(f" Indice {code} ({INDICES_CONOCIDOS[code]})...")
result[f"indice_{code}"] = fetch_indice(code)
time.sleep(0.3)
except Exception as e:
log.warning(f" indice {code}: {e}")
result[f"indice_{code}"] = {"error": str(e)}
return result
# ── CLI ────────────────────────────────────────────────────────────────────
MODES = ["panel", "historico", "indice", "bond-info", "all"]
def main():
parser = argparse.ArgumentParser(
description="BYMA Data Fetcher — Bolsas y Mercados Argentinos"
)
parser.add_argument("mode", choices=MODES, help="Modo")
parser.add_argument(
"arg", nargs="?",
help="Argumento: panel name | symbol | indice code"
)
parser.add_argument(
"--page", type=int, default=1,
help="Pagina (1-indexed). NOTA: ignorada por la API — usar --all"
)
parser.add_argument(
"--page-size", type=int, default=200,
help="Items por pagina (default: 200; usar grande para 'all')"
)
parser.add_argument(
"--all", action="store_true",
help="Trae todo de una sola llamada (page_size=5000)"
)
parser.add_argument(
"--t0", action="store_true",
help="Solo settlementType=1 (CI/Contado Inmediato)"
)
parser.add_argument(
"--t1", action="store_true",
help="Solo settlementType=2 (24hs)"
)
parser.add_argument("--desde", help="Fecha desde YYYY-MM-DD (historicos)")
parser.add_argument("--hasta", help="Fecha hasta YYYY-MM-DD (historicos)")
parser.add_argument(
"--resolution", default="D",
help="Resolucion historico: D, W, M (default: D)"
)
parser.add_argument("-o", "--output", help="Guardar a archivo JSON")
parser.add_argument("-q", "--quiet", action="store_true", help="Modo silencioso")
args = parser.parse_args()
if args.quiet:
log.setLevel(logging.WARNING)
try:
if args.mode == "panel":
if not args.arg:
log.error(f"Modo 'panel' requiere nombre. Validos: {list(PANELS)}")
sys.exit(1)
result = fetch_panel(
args.arg, page=args.page, page_size=args.page_size,
t0=args.t0, t1=args.t1, fetch_all=args.all,
)
elif args.mode == "historico":
if not args.arg:
log.error("Modo 'historico' requiere simbolo (ej: 'GGAL 24HS')")
sys.exit(1)
result = fetch_historico(
args.arg, desde=args.desde, hasta=args.hasta,
resolution=args.resolution,
)
elif args.mode == "indice":
if not args.arg:
log.error(f"Modo 'indice' requiere codigo. Conocidos: {INDICES_CONOCIDOS}")
sys.exit(1)
result = fetch_indice(
args.arg.upper(), desde=args.desde, hasta=args.hasta,
resolution=args.resolution,
)
elif args.mode == "bond-info":
if not args.arg:
log.error("Modo 'bond-info' requiere ticker (ej: 'AE38', 'AL30', 'TY30P')")
sys.exit(1)
result = fetch_bond_info(args.arg.upper())
elif args.mode == "all":
result = fetch_all()
else:
parser.print_help()
sys.exit(1)
except requests.HTTPError as e:
log.error(f"HTTP Error: {e}")
if e.response is not None:
log.error(f"Body: {e.response.text[:500]}")
sys.exit(1)
except Exception as e:
log.error(f"Error: {e}")
sys.exit(1)
if args.output:
with open(args.output, "w", encoding="utf-8") as f:
json.dump(result, f, indent=2, ensure_ascii=False)
log.info(f"Guardado: {args.output}")
else:
print(json.dumps(result, indent=2, ensure_ascii=False))
if __name__ == "__main__":
main()