원클릭으로
primary
Trading API de Primary (Matba ROFEX): futuros, opciones, acciones, bonos. Órdenes, posiciones, cuenta, market data.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Trading API de Primary (Matba ROFEX): futuros, opciones, acciones, bonos. Órdenes, posiciones, cuenta, market data.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
History of Market (historyofmarket.com) — API publica con 88 datasets historicos de indices US desde 1871. S&P 500 (price, CAPE, EPS, drawdowns, changes, constituents), Nasdaq Composite/Nasdaq 100 (price, volatility, VXN, changes), Dow Jones, SOX/SMH, sector ETFs (XLK, XLF), Magnificent 7 y macro. Sin API key, CORS libre, CC BY 4.0.
API no oficial de Yahoo Finance: precios, históricos, fundamentales, opciones, noticias en JSON puro sin wrappers.
Construcción y optimización cuantitativa de portafolios: Markowitz (scipy.optimize + Monte Carlo), Black-Litterman (prior CAPM, views absolutas/relativas, posterior bayesiano), HRP/HERC/NCO (clustering jerárquico, risk parity, NCO con restricciones). Todo flat numpy + scipy, sin Riskfolio-Lib ni PyPortfolioOpt.
Academic backtesting framework for quantitative research. ~30 risk and performance ratios, 10 classes of indicators, event-driven engine with 6+ strategies, MPT optimizer, forward-looking simulation with Johnson SU + t-Copula, walk-forward CV, stress testing, fundamental analysis (Altman Z, Piotroski, DuPont). All flat Python + numpy.
Pricing completo de opciones europeas y americanas. 9 metodos: Black-Scholes, Binomial CRR, Trinomial, Monte Carlo (antithetic) + Longstaff-Schwartz, Bjerksund-Stensland 2002 / BAW (American closed-form), Heston 1993 (vol estocastica, sonrisa via Fourier), Bates 1996 (Heston + Merton jumps, crash risk), greeks (BS), implied vol, P(ITM) y P(Profit). Disenado para backtesting: cada funcion es flat Python vectorizado con numpy (sin abstracciones), usa math.erfc (no scipy). BS 2.4 us/op, BS2 3.6 us, Heston 400 us, Binomial N=500 5.6 ms. CLI con 15 modos mas validate y bench. Time complexity O(1) para todos los closed-form.
Datos macro y sociales de Argentina via la API oficial Series de Tiempo del Estado (apis.datos.gob.ar/series). ~4250 series del INDEC + BCRA + Min Economia + Sec Trabajo. Sin auth, sin API key. IPC nacional, EMAE, IPI, ISAC, EPH (desempleo), pobreza, comercio exterior, salarios (RIPTE, SMVM), tipo de cambio, reservas, REM expectativas. Transformaciones builtin (% YoY, % YTD, change) y agregacion temporal (daily→monthly→yearly) server-side. La API mas estable y mejor documentada del repo.
| name | primary |
| description | Trading API de Primary (Matba ROFEX): futuros, opciones, acciones, bonos. Órdenes, posiciones, cuenta, market data. |
| license | MIT |
API para operar en el Mercado Argentino de Futuros y Opciones (Matba ROFEX) a través de Primary Trading Platform (PTP). Soporta futuros (dólar, soja, trigo, maíz, índices), opciones sobre futuros, acciones, bonos y CEDEARs.
Base URL: https://api.remarkets.primary.com.ar
Docs: github.com/matbarofex — repositorio oficial con ejemplos open source.
| Entorno | URL | Descripción |
|---|---|---|
| REMARKET (demo) | remarkets.primary.ventures | Crear cuenta gratis para paper trading |
| LIVE (producción) | Contactar a mpi@primary.com.ar | Solicitar acceso al equipo MPI |
Una vez creada la cuenta en REMARKET, tendrás:
REM + últimos dígitos del usuario)import requests
r = requests.post("https://api.remarkets.primary.com.ar/auth/getToken",
headers={"X-Username": tu_usuario, "X-Password": tu_password})
token = r.headers["X-Auth-Token"]
El token se envía en adelante como header X-Auth-Token en todos los requests.
⚠️ NUNCA hardcodear credenciales. Usar variables de entorno o parámetros CLI.
import os
TOKEN = os.getenv("PRIMARY_TOKEN") # Opcional: cachear token
USER = os.getenv("PRIMARY_USER")
PASS = os.getenv("PRIMARY_PASSWORD")
ACCOUNT = os.getenv("PRIMARY_ACCOUNT") # Ej: 12345 o REM12345
Si recibís un 401, el token expiró. Renovalo con un nuevo POST a /auth/getToken.
El mercado se organiza en segmentos (ruedas de negociación). Cada instrumento pertenece a un segmento.
| Segmento | Descripción |
|---|---|
DDF | Derivados Financieros (futuros de dólar, índices) |
DDA | Derivados Agropecuarios (soja, trigo, maíz) |
DUAL | Instrumentos listados en ambas divisiones |
MERV | Mercados externos a Matba ROFEX (BYMA) |
MAE | Mercado Abierto Electrónico |
TEST | Ambiente de pruebas |
U-DDF, U-DDA, U-DUAL, U-FIN, U-COMM, U-STOCK | Sub-segmentos de usuarios |
TIVA, AVS | Otros segmentos |
GET https://api.remarkets.primary.com.ar/rest/segment/all
r = requests.get("https://api.remarkets.primary.com.ar/rest/segment/all",
headers={"X-Auth-Token": token})
print(r.json()["segments"])
Respuesta:
{"status":"OK","segments":[
{"marketSegmentId":"DDF","marketId":"ROFX"},
{"marketSegmentId":"DDA","marketId":"ROFX"},
...
]}
Los instrumentos se identifican por su símbolo y marketId. Ejemplos:
| Símbolo | Descripción | CFI Code |
|---|---|---|
DLR/JUN26 | Futuro de dólar Junio 2026 | FXXXSX |
SOJ.ROS/MAY26 | Futuro de soja Rosario Mayo 2026 | FXXXSX |
DLR/JUN26 1460 C | Opción Call sobre futuro dólar | OCAFXS |
DLR/JUN26 1420 P | Opción Put sobre futuro dólar | OPAFXS |
GGAL | Acción Grupo Galicia | ESXXXX |
GET https://api.remarkets.primary.com.ar/rest/instruments/all
GET https://api.remarkets.primary.com.ar/rest/instruments/details
Devuelve: symbol, segment, lowLimitPrice, highLimitPrice, minPriceIncrement, minTradeVol, maxTradeVol, tickSize, contractMultiplier, roundLot, maturityDate, currency, orderTypes, timesInForce, cficode.
GET https://api.remarkets.primary.com.ar/rest/instruments/detail?symbol=DLR/JUN26&marketId=ROFX
GET https://api.remarkets.primary.com.ar/rest/instruments/byCFICode?CFICode=FXXXSX
| CFI Code | Tipo |
|---|---|
FXXXSX | Futuro |
FXXXXX | Futuro (genérico) |
OCAFXS | Opción Call sobre Futuro |
OPAFXS | Opción Put sobre Futuro |
OCEFXS | Opción Call europea sobre Futuro |
OPEFXS | Opción Put europea sobre Futuro |
ESXXXX | Acción |
DBXXXX | Bono |
EMXXXX | CEDEAR |
OCASPS | Opción Call sobre Acción |
OPASPS | Opción Put sobre Acción |
DBXXFR | Obligación Negociable |
GET https://api.remarkets.primary.com.ar/rest/instruments/bySegment?MarketSegmentID=DDF&MarketID=ROFX
GET https://api.remarkets.primary.com.ar/rest/marketdata/get
?marketId=ROFX
&symbol=DLR/JUN26
&entries=BI,OF,LA,OP,CL,SE,OI
&depth=3
| Entry | Significado |
|---|---|
BI | Bids (ofertas de compra en el book) |
OF | Offers (ofertas de venta en el book) |
LA | Last (último precio operado) |
OP | Opening Price (precio de apertura) |
CL | Closing Price (cierre rueda anterior) |
SE | Settlement Price (precio de ajuste, solo futuros) |
HI | High Price (máximo de la rueda) |
LO | Low Price (mínimo de la rueda) |
TV | Trade Volume (volumen operado en contratos) |
OI | Open Interest (interés abierto, solo futuros) |
IV | Index Value (solo índices) |
EV | Effective Volume (solo BYMA) |
NV | Nominal Volume (solo BYMA) |
ACP | Auction Price (cierre del día corriente) |
r = requests.get("https://api.remarkets.primary.com.ar/rest/marketdata/get",
headers={"X-Auth-Token": token},
params={"marketId": "ROFX", "symbol": "DLR/JUN26",
"entries": "BI,OF,LA,OP,CL,SE,OI", "depth": 3})
data = r.json()["marketData"]
print(f"Bid: {data['BI']} | Offer: {data['OF']}")
print(f"Last: {data['LA']} | Settle: {data['SE']}")
GET https://api.remarkets.primary.com.ar/rest/data/getTrades
?marketId=ROFX
&symbol=DLR/JUN26
&dateFrom=2026-06-01
&dateTo=2026-06-08
Parámetros: marketId, symbol, date (una fecha), dateFrom/dateTo (rango), external (para mercados externos), environment (REMARKETS).
r = requests.get("https://api.remarkets.primary.com.ar/rest/data/getTrades",
headers={"X-Auth-Token": token},
params={"marketId": "ROFX", "symbol": "DLR/JUN26",
"date": "2026-06-05"})
trades = r.json()["trades"]
for t in trades[:3]:
print(f"{t['datetime']} {t['price']} {t['size']}")
| Tipo | Descripción |
|---|---|
LIMIT | Orden con precio límite |
MARKET | Orden a mercado |
STOP_LIMIT | Orden stop que se activa como limit |
MARKET_TO_LIMIT | Market que se convierte en limit |
Nota: STOP_LIMIT y MARKET_TO_LIMIT no están disponibles para todos los instrumentos. Verificar orderTypes en el detalle del instrumento.
| TIF | Descripción |
|---|---|
DAY | Solo válida por el día. Se expira al cierre de rueda |
IOC | Immediate or Cancel |
FOK | Fill or Kill |
GTD | Good Till Date (requiere expireDate) |
GET https://api.remarkets.primary.com.ar/rest/order/newSingleOrder
?marketId=ROFX
&symbol=DLR/JUN26
&side=BUY
&orderQty=10
&ordType=LIMIT
&price=1450.0
&timeInForce=DAY
&account=TU_CUENTA
&cancelPrevious=False
&iceberg=False
Parámetros:
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
marketId | String | ✅ | ROFX |
symbol | String | ✅ | Símbolo del instrumento |
side | String | ✅ | BUY o SELL |
orderQty | Integer | ✅ | Cantidad de contratos |
ordType | String | ✅ | LIMIT o MARKET |
price | Float | Condicional | Requerido para LIMIT |
timeInForce | String | No | DAY (default), IOC, FOK, GTD |
account | Integer/String | ✅ | Número de cuenta |
cancelPrevious | Boolean | No | Cancela órdenes previas del mismo contrato/lado |
iceberg | Boolean | No | Orden Iceberg (default: false) |
displayQty | Integer | Condicional | Cantidad a divulgar (para iceberg) |
expireDate | Date | Condicional | Requerido para GTD (formato: YYYYMMDD) |
Respuesta:
{"status":"OK","order":{"clientId":"21581341758","proprietary":"PBCP"}}
El clientId es el clOrdId (Client Order ID) que se usa para consultar/cancelar la orden.
{"type":"no","product":{"marketId":"ROFX","symbol":"DLR/JUN26"},
"price":185,"quantity":23,"side":"BUY","account":"20","iceberg":false}
Para identificar la orden vía WebSocket, incluir wsClOrdId:
{"type":"no","product":{"marketId":"ROFX","symbol":"DLR/JUN26"},
"price":185,"quantity":23,"side":"BUY","account":"20",
"iceberg":false,"wsClOrdId":"mioid-unico-123"}
Respuesta WebSocket (Execution Report):
{"type":"or","orderReport":{"orderId":"1128056","clOrdId":"user14545...",
"status":"PENDING_NEW","text":"Enviada","wsClOrdId":"mioid-unico-123"}}
Importante: El
wsClOrdIdsolo aparece en el primer execution report. Luego se debe usar elclOrdIddevuelto para seguimiento.
GET https://api.remarkets.primary.com.ar/rest/order/replaceById
?clOrdId=user144733478280357
&proprietary=api
&price=17
&orderQty=10
GET https://api.remarkets.primary.com.ar/rest/order/cancelById
?clOrdId=ajduj3l13ieci2jr4ck
&proprietary=PBCP
{"type":"co","clientId":"user114121092035207","proprietary":"PBCP"}
| Endpoint | Descripción |
|---|---|
GET /rest/order/id?clOrdId=...&proprietary=api | Último estado del request |
GET /rest/order/allById?clOrdId=...&proprietary=api | Todos los estados del request |
GET /rest/order/byOrderId?orderId=... | Estado por Order ID |
GET /rest/order/actives?accountId=10 | Órdenes activas (NEW o PARTIALLY_FILLED) |
GET /rest/order/filleds?accountId=10 | Órdenes total o parcialmente operadas |
GET /rest/order/all?accountId=10 | Todos los estados de la cuenta |
GET /rest/order/byExecId?execId=T1234567 | Estado por Execution ID |
Suscribirse a una cuenta:
{"type":"os","account":{"id":"40"}}
Varias cuentas:
{"type":"os","accounts":[{"id":"40"},{"id":"4000"}]}
Todas las cuentas:
{"type":"os"}
Solo órdenes activas:
{"type":"os","snapshotOnlyActive":true}
La Risk API usa HTTP Basic Auth con el mismo user/password, no token. Requiere el header Authorization: Basic <base64> adicionalmente al X-Auth-Token.
import base64
auth = base64.b64encode(f"{user}:{password}".encode()).decode()
headers = {"X-Auth-Token": token, "Authorization": f"Basic {auth}"}
GET https://api.remarkets.primary.com.ar/rest/risk/position/getPositions/{accountName}
r = requests.get(f"https://api.remarkets.primary.com.ar/rest/risk/position/getPositions/TU_CUENTA",
headers=headers)
positions = r.json()["positions"]
for p in positions:
print(f"{p['symbol']} Buy:{p['buySize']} Sell:{p['sellSize']} Diff:{p['totalDiff']}")
GET https://api.remarkets.primary.com.ar/rest/risk/detailedPosition/{accountName}
Devuelve desglose por instrumento con: contractType, marketPrice, currency, exchangeRate, contractMultiplier, buyCurrentSize, sellCurrentSize, detailedDailyDiff.
GET https://api.remarkets.primary.com.ar/rest/risk/accountReport/{accountName}
import base64
auth = base64.b64encode(f"{user}:{password}".encode()).decode()
headers = {"X-Auth-Token": token, "Authorization": f"Basic {auth}"}
r = requests.get(f"https://api.remarkets.primary.com.ar/rest/risk/accountReport/TU_CUENTA",
headers=headers)
data = r.json()["accountData"]
print(f"Colateral: {data['collateral']}")
print(f"Margen: {data['margin']}")
print(f"Disponible: {data['availableToCollateral']}")
# Saldos por moneda
for moneda, saldo in data['detailedAccountReports']['0']['currencyBalance']['detailedCurrencyBalance'].items():
print(f" {moneda}: consumido={saldo['consumed']} disponible={saldo['available']}")
URL: wss://api.remarkets.primary.com.ar/
La API WebSocket recibe mensajes asíncronos. El token se envía como header en la conexión:
import websocket
ws = websocket.WebSocketApp(
"wss://api.remarkets.primary.com.ar/",
header=[f"X-Auth-Token: {token}"],
on_open=on_open,
on_message=on_message,
...
)
ws.run_forever()
Los mensajes tienen el formato:
| type | Significado |
|---|---|
no | New Order (enviar orden) |
co | Cancel Order (cancelar orden) |
or | Order Report (execution report recibido) |
os | Order Subscription (suscribirse a reports) |
smd | Subscribe Market Data |
Md | Market Data (recibido) |
{"type":"smd","level":1,"entries":["OF","BI","LA"],
"products":[{"symbol":"DLR/JUN26","marketId":"ROFX"}],"depth":2}
Respuesta:
{"type":"Md","instrumentId":{"marketId":"ROFX","symbol":"DLR/JUN26"},
"marketData":{"OF":[{"price":189,"size":21},{"price":188,"size":13}]}}
| Estado | Significado |
|---|---|
PENDING_NEW | Enviada al mercado, aún no procesada |
NEW | Aceptada, activa en el book |
PARTIALLY_FILLED | Parcialmente operada |
FILLED | Totalmente operada |
CANCELLED | Cancelada |
REJECTED | Rechazada (ver text para motivo) |
PENDING_CANCEL | Cancelación en proceso |
PENDING_REPLACE | Reemplazo en proceso |
REPLACED | Reemplazada |
PENDING_APPROVAL | Pendiente de aprobación |
| Error | Causa | Solución |
|---|---|---|
| 401 Unauthorized | Token inválido o expirado | Renovar con /auth/getToken |
"No tiene acceso a la cuenta" | Account ID incorrecto | Verificar accountId |
"Product doesn't exist" | Symbol incorrecto | Verificar símbolo con instruments/all |
"Access Denied" | Sin permisos para el endpoint | Verificar segmento/método |
"Ruta invalida" | Endpoint no existe | Revisar URL |
| Bid/Offer vacíos | Mercado cerrado o sin liquidez | Consultar en horario de rueda |
Ver ./scripts/:
# Autenticación y token (opcional, los scripts hacen login automático)
export PRIMARY_USER="tu_usuario"
export PRIMARY_PASSWORD="tu_password"
export PRIMARY_ACCOUNT="TU_CUENTA"
# Listar segmentos e instrumentos
python scripts/instruments.py --user $PRIMARY_USER --password $PRIMARY_PASSWORD
# Market data de un futuro
python scripts/market_data.py --user $PRIMARY_USER --password $PRIMARY_PASSWORD \
--symbol DLR/JUN26 --entries BI,OF,LA
# Ver reporte de cuenta
python scripts/check_account.py --user $PRIMARY_USER --password $PRIMARY_PASSWORD \
--account TU_CUENTA
# Ver posiciones
python scripts/check_positions.py --user $PRIMARY_USER --password $PRIMARY_PASSWORD \
--account TU_CUENTA
# Enviar orden (¡cuidado! orden real en live)
python scripts/place_order.py --user $PRIMARY_USER --password $PRIMARY_PASSWORD \
--symbol DLR/JUN26 --side BUY --qty 1 --type LIMIT --price 1450 --account TU_CUENTA
# WebSocket: Market Data en tiempo real
python scripts/websocket_md.py --user $PRIMARY_USER --password $PRIMARY_PASSWORD \
--symbols DLR/JUN26 --entries BI,OF,LA --depth 3
# WebSocket: Execution Reports
python scripts/websocket_orders.py --user $PRIMARY_USER --password $PRIMARY_PASSWORD \
--account TU_CUENTA
# WebSocket: Enviar orden (requiere suscripción a execution reports aparte)
python scripts/websocket_send_order.py --user $PRIMARY_USER --password $PRIMARY_PASSWORD \
--symbol DLR/JUN26 --side BUY --qty 1 --type LIMIT --price 1450 --account TU_CUENTA
# WebSocket: Cancelar orden
python scripts/websocket_send_order.py --user $PRIMARY_USER --password $PRIMARY_PASSWORD \
--cancel --clordid user12345... --proprietary PBCP
| Campo | Descripción |
|---|---|
clOrdId | Client Order ID — ID del request al mercado |
orderId | Order ID — ID de la orden en el mercado |
execId | Execution ID — ID de una ejecución particular |
proprietary | Usuario FIX que envió la orden (PBCP o ISV_PBCP) |
wsClOrdId | ID de orden enviada por WebSocket (solo en 1er report) |
avgPx | Precio promedio operado |
cumQty | Cantidad acumulada operada |
leavesQty | Cantidad remanente |
lastPx | Último precio operado |
lastQty | Última cantidad operada |
transactTime | Fecha y hora de la transacción |
tickSize | Incremento mínimo de cantidad |
minPriceIncrement | Incremento mínimo de precio (tick price) |
contractMultiplier | Multiplicador del contrato |
maturityDate | Fecha de vencimiento |
priceConvertionFactor | Factor para precio unitario |
lowLimitPrice | Límite mínimo de precio |
highLimitPrice | Límite máximo de precio |