Primary logo

Primary

Community
gauss314
primary

Trading API de Primary (Matba ROFEX): futuros, opciones, acciones, bonos. Órdenes, posiciones, cuenta, market data.

Overview

Publishergauss314
Repositoryskills
Skill nameprimary
Stars
250
Forks
35
Bundled files
9
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 9 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by gauss314 on GitHub. Read the source before you install it.

Installation

Install the Primary AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/gauss314/skills/tree/main/skills/primary
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/gauss314/skills.git /tmp/skills
mkdir -p .claude/skills
cp -r /tmp/skills/skills/primary .claude/skills/primary
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Primary in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Primary on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Primary is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Primary — Trading API de Matba ROFEX

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.


Autenticación

Obtener Credenciales

EntornoURLDescripción
REMARKET (demo)remarkets.primary.venturesCrear cuenta gratis para paper trading
LIVE (producción)Contactar a mpi@primary.com.arSolicitar acceso al equipo MPI

Una vez creada la cuenta en REMARKET, tendrás:

  • Usuario: el que registraste
  • Password: el que configuraste
  • Account: tu número de cuenta (suele ser REM + últimos dígitos del usuario)

Obtener Token

python
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.

python
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

Renew Token

Si recibís un 401, el token expiró. Renovalo con un nuevo POST a /auth/getToken.


Segmentos

El mercado se organiza en segmentos (ruedas de negociación). Cada instrumento pertenece a un segmento.

SegmentoDescripción
DDFDerivados Financieros (futuros de dólar, índices)
DDADerivados Agropecuarios (soja, trigo, maíz)
DUALInstrumentos listados en ambas divisiones
MERVMercados externos a Matba ROFEX (BYMA)
MAEMercado Abierto Electrónico
TESTAmbiente de pruebas
U-DDF, U-DDA, U-DUAL, U-FIN, U-COMM, U-STOCKSub-segmentos de usuarios
TIVA, AVSOtros segmentos

Listar Segmentos

http
GET https://api.remarkets.primary.com.ar/rest/segment/all
python
r = requests.get("https://api.remarkets.primary.com.ar/rest/segment/all",
    headers={"X-Auth-Token": token})
print(r.json()["segments"])

Respuesta:

json
{"status":"OK","segments":[
  {"marketSegmentId":"DDF","marketId":"ROFX"},
  {"marketSegmentId":"DDA","marketId":"ROFX"},
  ...
]}

Instrumentos (Securities)

Los instrumentos se identifican por su símbolo y marketId. Ejemplos:

SímboloDescripciónCFI Code
DLR/JUN26Futuro de dólar Junio 2026FXXXSX
SOJ.ROS/MAY26Futuro de soja Rosario Mayo 2026FXXXSX
DLR/JUN26 1460 COpción Call sobre futuro dólarOCAFXS
DLR/JUN26 1420 POpción Put sobre futuro dólarOPAFXS
GGALAcción Grupo GaliciaESXXXX

Todos los Instrumentos

http
GET https://api.remarkets.primary.com.ar/rest/instruments/all

Instrumentos con Detalle

http
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.

Detalle de un Instrumento

http
GET https://api.remarkets.primary.com.ar/rest/instruments/detail?symbol=DLR/JUN26&marketId=ROFX

Por Código CFI

http
GET https://api.remarkets.primary.com.ar/rest/instruments/byCFICode?CFICode=FXXXSX
CFI CodeTipo
FXXXSXFuturo
FXXXXXFuturo (genérico)
OCAFXSOpción Call sobre Futuro
OPAFXSOpción Put sobre Futuro
OCEFXSOpción Call europea sobre Futuro
OPEFXSOpción Put europea sobre Futuro
ESXXXXAcción
DBXXXXBono
EMXXXXCEDEAR
OCASPSOpción Call sobre Acción
OPASPSOpción Put sobre Acción
DBXXFRObligación Negociable

Por Segmento

http
GET https://api.remarkets.primary.com.ar/rest/instruments/bySegment?MarketSegmentID=DDF&MarketID=ROFX

Market Data

En Tiempo Real (REST Snapshot)

http
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
EntrySignificado
BIBids (ofertas de compra en el book)
OFOffers (ofertas de venta en el book)
LALast (último precio operado)
OPOpening Price (precio de apertura)
CLClosing Price (cierre rueda anterior)
SESettlement Price (precio de ajuste, solo futuros)
HIHigh Price (máximo de la rueda)
LOLow Price (mínimo de la rueda)
TVTrade Volume (volumen operado en contratos)
OIOpen Interest (interés abierto, solo futuros)
IVIndex Value (solo índices)
EVEffective Volume (solo BYMA)
NVNominal Volume (solo BYMA)
ACPAuction Price (cierre del día corriente)
python
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']}")

Histórica (Trades)

http
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).

python
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']}")

Órdenes

Tipos de Órdenes

TipoDescripción
LIMITOrden con precio límite
MARKETOrden a mercado
STOP_LIMITOrden stop que se activa como limit
MARKET_TO_LIMITMarket 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.

Time in Force (TIF)

TIFDescripción
DAYSolo válida por el día. Se expira al cierre de rueda
IOCImmediate or Cancel
FOKFill or Kill
GTDGood Till Date (requiere expireDate)

Ingresar Orden (REST)

http
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ámetroTipoObligatorioDescripción
marketIdString✅ROFX
symbolString✅Símbolo del instrumento
sideString✅BUY o SELL
orderQtyInteger✅Cantidad de contratos
ordTypeString✅LIMIT o MARKET
priceFloatCondicionalRequerido para LIMIT
timeInForceStringNoDAY (default), IOC, FOK, GTD
accountInteger/String✅Número de cuenta
cancelPreviousBooleanNoCancela órdenes previas del mismo contrato/lado
icebergBooleanNoOrden Iceberg (default: false)
displayQtyIntegerCondicionalCantidad a divulgar (para iceberg)
expireDateDateCondicionalRequerido para GTD (formato: YYYYMMDD)

Respuesta:

json
{"status":"OK","order":{"clientId":"21581341758","proprietary":"PBCP"}}

El clientId es el clOrdId (Client Order ID) que se usa para consultar/cancelar la orden.

Ingresar Orden (WebSocket)

json
{"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:

json
{"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):

json
{"type":"or","orderReport":{"orderId":"1128056","clOrdId":"user14545...",
 "status":"PENDING_NEW","text":"Enviada","wsClOrdId":"mioid-unico-123"}}

Importante: El wsClOrdId solo aparece en el primer execution report. Luego se debe usar el clOrdId devuelto para seguimiento.

Reemplazar Orden

http
GET https://api.remarkets.primary.com.ar/rest/order/replaceById
    ?clOrdId=user144733478280357
    &proprietary=api
    &price=17
    &orderQty=10

Cancelar Orden

http
GET https://api.remarkets.primary.com.ar/rest/order/cancelById
    ?clOrdId=ajduj3l13ieci2jr4ck
    &proprietary=PBCP

Cancelar por WebSocket

json
{"type":"co","clientId":"user114121092035207","proprietary":"PBCP"}

Consultar Estado de la Orden (REST)

EndpointDescripción
GET /rest/order/id?clOrdId=...&proprietary=apiÚltimo estado del request
GET /rest/order/allById?clOrdId=...&proprietary=apiTodos 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=10Todos los estados de la cuenta
GET /rest/order/byExecId?execId=T1234567Estado por Execution ID

Execution Reports (WebSocket)

Suscribirse a una cuenta:

json
{"type":"os","account":{"id":"40"}}

Varias cuentas:

json
{"type":"os","accounts":[{"id":"40"},{"id":"4000"}]}

Todas las cuentas:

json
{"type":"os"}

Solo órdenes activas:

json
{"type":"os","snapshotOnlyActive":true}

Risk API

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.

python
import base64
auth = base64.b64encode(f"{user}:{password}".encode()).decode()
headers = {"X-Auth-Token": token, "Authorization": f"Basic {auth}"}

Posiciones de una Cuenta

http
GET https://api.remarkets.primary.com.ar/rest/risk/position/getPositions/{accountName}
python
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']}")

Posiciones Detalladas

http
GET https://api.remarkets.primary.com.ar/rest/risk/detailedPosition/{accountName}

Devuelve desglose por instrumento con: contractType, marketPrice, currency, exchangeRate, contractMultiplier, buyCurrentSize, sellCurrentSize, detailedDailyDiff.

Reporte de Cuenta

http
GET https://api.remarkets.primary.com.ar/rest/risk/accountReport/{accountName}
python
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']}")

WebSocket

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:

python
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:

typeSignificado
noNew Order (enviar orden)
coCancel Order (cancelar orden)
orOrder Report (execution report recibido)
osOrder Subscription (suscribirse a reports)
smdSubscribe Market Data
MdMarket Data (recibido)

Market Data por WebSocket

json
{"type":"smd","level":1,"entries":["OF","BI","LA"],
 "products":[{"symbol":"DLR/JUN26","marketId":"ROFX"}],"depth":2}

Respuesta:

json
{"type":"Md","instrumentId":{"marketId":"ROFX","symbol":"DLR/JUN26"},
 "marketData":{"OF":[{"price":189,"size":21},{"price":188,"size":13}]}}

Estados de una Orden

EstadoSignificado
PENDING_NEWEnviada al mercado, aún no procesada
NEWAceptada, activa en el book
PARTIALLY_FILLEDParcialmente operada
FILLEDTotalmente operada
CANCELLEDCancelada
REJECTEDRechazada (ver text para motivo)
PENDING_CANCELCancelación en proceso
PENDING_REPLACEReemplazo en proceso
REPLACEDReemplazada
PENDING_APPROVALPendiente de aprobación

Errores Comunes

ErrorCausaSolución
401 UnauthorizedToken inválido o expiradoRenovar con /auth/getToken
"No tiene acceso a la cuenta"Account ID incorrectoVerificar accountId
"Product doesn't exist"Symbol incorrectoVerificar símbolo con instruments/all
"Access Denied"Sin permisos para el endpointVerificar segmento/método
"Ruta invalida"Endpoint no existeRevisar URL
Bid/Offer vacíosMercado cerrado o sin liquidezConsultar en horario de rueda

Scripts de Ejemplo

Ver ./scripts/:

bash
# 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

Glosario de Campos

CampoDescripción
clOrdIdClient Order ID — ID del request al mercado
orderIdOrder ID — ID de la orden en el mercado
execIdExecution ID — ID de una ejecución particular
proprietaryUsuario FIX que envió la orden (PBCP o ISV_PBCP)
wsClOrdIdID de orden enviada por WebSocket (solo en 1er report)
avgPxPrecio promedio operado
cumQtyCantidad acumulada operada
leavesQtyCantidad remanente
lastPxÚltimo precio operado
lastQtyÚltima cantidad operada
transactTimeFecha y hora de la transacción
tickSizeIncremento mínimo de cantidad
minPriceIncrementIncremento mínimo de precio (tick price)
contractMultiplierMultiplicador del contrato
maturityDateFecha de vencimiento
priceConvertionFactorFactor para precio unitario
lowLimitPriceLímite mínimo de precio
highLimitPriceLímite máximo de precio

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Primary AI skill do?

Trading API de Primary (Matba ROFEX): futuros, opciones, acciones, bonos. Órdenes, posiciones, cuenta, market data.

Why use Primary on TypingMind?

Because you install it once and use it with any model. Primary is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Primary in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/gauss314/skills/tree/main/skills/primary. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Primary?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Primary?

As many as you like. As long as a model supports skills, you can use Primary with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Primary AI skill free?

Yes. It is published on GitHub by gauss314 under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇