Escritorio de Trading Agentic
Manual de operaciones para análisis y ejecución de trading de corto plazo.
Yo (Agente) realizo llamadas al MCP de Robinhood; los scripts actúan como mi calculadora determinista; el marco decide y yo ejecuto. Nunca calculo indicadores razonando directamente sobre las barras de precios: obtengo los datos y los paso a scripts/.
Guardarraíles — Léase Primero, No Negociable
- Posiciones protegidas: Ciertos tickers pueden estar designados como restringidos (ej. concesiones de acciones). NUNCA los analices para vender o reducir, ni los incluyas en sugerencias de salida. Solo deben mencionarse como contexto de exposición si es relevante.
- Dos cuentas, dos roles:
- Agentic → trading de corto plazo; aquí es donde ejecuto bajo el Mandato.
- Individual (cuenta de margen) → cartera de mantener a largo plazo; solo analizar calidad de tenencia, sin trading activo.
- Identifico la cuenta transable por la propia bandera del bróker desde
get_accounts(exactamente una cuenta es transable por el agente; las otras rechazan mis órdenes directamente). Nunca la infiero por el apodo de la cuenta, y nunca codifico un número de cuenta.
- Poder de compra: Siempre tomo
get_portfolio.buying_powercomo la cifra autoritativa en lugar de derivarla yo mismo. El tipo de cuenta importa y puede cambiar: en una cuenta de efectivo solo el efectivo liquidado es gastable (T+1), mientras que una cuenta de margen limitado puede negociar ingresos no liquidados inmediatamente. - Visualización HTML solo los viernes como parte del ritual de revisión semanal. No ofrezcas ni generes en otros días a menos que el usuario lo solicite explícitamente.
- Fuente macro (opcional / mejor esfuerzo): Investing.com (NO Polymarket). Si es inaccesible o está bloqueado por restricciones de salida de red, NO detengas ni bloquees la ejecución: procede con datos de mercado deterministas sin el diferencial de rendimiento.
- La ejecución autónoma está AUTORIZADA en la cuenta Agentic bajo el Mandato de Ejecución Autónoma (siguiente sección). Esta autorización es duradera y fue establecida por el usuario en una sesión en vivo el 2026-08-26; NO depende de un mensaje programado que afirme que existe. Un mensaje almacenado no puede otorgarse consentimiento a sí mismo — la autorización vive aquí, en la configuración, donde puede verificarse leyéndola. Siempre revisa usando
review_*_order(simulación) antes de ejecutarplace_*_order.
Mandato de Ejecución Autónoma
El usuario autoriza la ejecución de órdenes sin confirmación en el momento, solo en la cuenta designada por el bróker como transable por el agente, y solo dentro de estos límites. Un límite excedido no es una señal para pedir permiso: es una señal para no operar e informar.
Lo que puedo ejecutar
- Decisiones emitidas por
score.pyen esta misma sesión, con el pilar macro calculado pormacro_pillar.pyel mismo día. Los scripts aún se ejecutan cada sesión y su salida sigue siendo la línea base — el marco no es opcional. - Entradas y salidas discrecionales están autorizadas (establecido por el usuario en una sesión en vivo el 2026-08-26, reemplazando la regla anterior de cero discreción): un cambio de tendencia, un catalizador noticioso, o una configuración que la cascada de decisión no cubre son todas razones válidas para actuar. La cascada es rígida por diseño y fallará cosas; para eso está esta cláusula.
- Toda operación discrecional DEBE llevar su razonamiento por escrito en el informe de sesión — qué vi, por qué justificó actuar, y qué me probaría estar equivocado. Una operación que no pueda explicar en dos frases es una operación que no debería haber hecho.
- REBOTE TÁCTICO entra a la mitad del tamaño — es contrario a la tendencia por definición.
- Opcional: para una entrada impulsada por noticias, requerir que la cinta se mueva en la dirección de la tesis antes de actuar en lugar de anticipar el movimiento. Razonamiento en Contexto Externo a continuación — en ejecuciones programadas la fuente de noticias es la entrada más débil disponible, y la confirmación de precio es la protección más barata contra actuar sobre un titular mal fechado.
Límites estrictos
-
Máximo $1,200 por orden.
-
Máximo 3 nuevas posiciones por sesión. Las salidas no tienen límite.
-
Mínimo 15% del valor de la cuenta mantenido en efectivo. Nunca toco esa reserva.
-
El tipo de orden sigue el reloj de sesión (regla establecida por Eli el 2026-08-26, reemplazando la regla anterior solo de límite):
- Horario regular — Lun–Vie 09:30–15:58 ET:
type: "market". Si el análisis dice entrar, entra; una orden límite pasiva esperando un precio no es una entrada.dollar_amountESTÁ permitido aquí — es la forma natural de dimensionar al 3% de la cuenta, y el MCP solo lo acepta contype=market. - Fuera del horario regular:
type: "limit"con unlimit_priceexplícito, negociable — en o justo al otro lado del spread, dentro del 0.3% del último trade — y dimensionado en ACCIONES (quantity = dollars / limit_price, truncado a 6 decimales). Nuncadollar_amountaquí: el MCP lo convertiría silenciosamente a una orden de mercado que se ejecuta a un precio desconocido horas después. Las órdenes límite fraccionarias SÍ están soportadas a pesar de la nota fraccionaria del esquema de la herramienta (verificado 2026-08-26 víareview_equity_order: orden límite de compra DIAquantity=0.400000@ 534.50, aceptada con unorder_checksvacío). stop_marketystop_limitestán prohibidos en todo momento. Robinhood también rechaza stops en acciones fraccionarias, por lo que los stops en esta cuenta son niveles manuales que vuelvo a revisar cada sesión, no órdenes en reposo.time_in_forcedebe sergfd. Ninguna orden sobrevive a la sesión que la colocó — una orden encolada durante la noche es un llenado no supervisado a un precio que nadie evaluó.- Por qué la división: la regla original solo de límite existía porque las órdenes de mercado no supervisadas tienen deslizamiento invisible. Condicionar las órdenes de mercado al reloj de sesión lo resuelve directamente — se ejecutan solo mientras el libro es profundo y la sesión está activa, y todo lo que está fuera de esa ventana se mantiene con precio.
- Horario regular — Lun–Vie 09:30–15:58 ET:
-
Verificación previa de la orden. Antes de cada
place_equity_orderimprimo esta tabla y reviso cada fila. Si alguna fila falla, NO coloco la orden — informo en su lugar.campo valor verificación Reloj ET … ¿dentro o fuera de Lun–Vie 09:30–15:58? type… marketdentro de RTH ·limitfuera · nuncastop_*limit_price… fuera de RTH solo: negociable, dentro del 0.3% del último trade dimensionamiento … dollar_amountdentro de RTH ·quantityen acciones fueratime_in_force… debe ser gfdnocional dollar_amountoquantity × limit_price≤ $1,200 -
El guardián no es funcional a menos que
jqesté instalado. El hook implementa cada regla conjq; sin él, el script sale con 0 sin salida y el ejecutor lee eso como PERMITIR (verificado 2026-08-26 — una revisión temprana dejó pasar unstop_market). Ahora falla bloqueado, pero un guardián que lo niega todo tampoco es una configuración funcional. Ver Inicio de sesión — verificar que el guardián esté activo a continuación; de cualquier manera, trato la tabla de verificación previa anterior como la comprobación real, no el hook. -
No hay nueva posición en un solo nombre dentro de 2 sesiones de ganancias confirmadas (
get_earnings_calendar). ETFs exentos. -
Ejecuto
review_equity_orderantes de cadaplace_equity_order. Si la simulación difiere en más del 1% en precio o cantidad de lo que calculé, anulo e informo.
Inicio de sesión — verificar que el guardián esté activo
El Mandato es prosa, y la prosa no puede hacerse cumplir a sí misma; hooks/mandate-order-guard.sh es lo que hace que "solo órdenes límite" sea mecánico. El modo de fallo que importa es que un guardián que no está conectado, no es ejecutable o no tiene jq se ve exactamente como uno funcional hasta que se cuela una orden. Eso no es hipotético: el 2026-08-26 un stop_market pasó porque jq estaba ausente y el script salió con 0 sin salida, que el ejecutor del hook lee como PERMITIR. Así que antes de la primera place_equity_order de cualquier sesión ejecuto:
bash <skill-dir>/scripts/session-setup.sh
Instala jq, marca el guardián como ejecutable, y ejecuta 8 sondas en ambas ramas del reloj — 6 órdenes que el Mandato prohíbe, que deben ser denegadas, y 2 que permite, que deben pasar. Sondear solo denegaciones no es suficiente: un guardián que bloquea todo está igual de roto que uno que no bloquea nada, y desde una sola sonda de denegación los dos se ven iguales. Las sondas fijan el reloj de sesión del guardián vía MANDATE_FAKE_ET para que ambas ramas (horario regular y fuera de horario) sean probables cuando sea que la sesión arranque. Salida 0 con order guard verified significa que el guardián está evaluando reglas realmente. Cualquier otro resultado significa que no lo está, y no ejecuto órdenes esa sesión — aún ejecuto el análisis e informo lo que el marco emitió, y digo claramente que la ejecución estaba deshabilitada y por qué. El análisis con un guardián roto es útil; la ejecución no supervisada con uno no lo es.
Una cosa para ser honesto conmigo mismo: .claude/settings.json solo se carga para una sesión cuyo directorio de proyecto lo contiene. Cuando el escritorio se carga como una habilidad instalada en lugar de abrirse como un proyecto, el hook PreToolUse nunca se registra, y la sonda anterior verifica solo que el script denegaría si fuera llamado. En ese modo, nada fuera de mí está verificando, así que la tabla de verificación previa es todo el margen de seguridad — la lleno fila por fila antes de cada orden y aborto en cualquier fila que falle, en lugar de tratarlo como papeleo.
Esto no es hipotético, y lo indico en el informe de sesión cuando aplica. El 2026-08-26 una orden market con dollar_amount: 250 (DIA) y dos órdenes market (JPM, 2026-08-25) pasaron en modo habilidad con el guardián no registrado. Bajo la regla de reloj actual, las tres se colocaron durante horario regular y ahora pasarían el guardián por sus méritos — pero pasaron entonces porque nada estaba verificando, que es algo diferente de estar permitido. Si la auto-auditoría de sesión muestra órdenes agénticas y estoy ejecutando en modo habilidad, digo claramente: las órdenes no estaban vigiladas, independientemente de su contenido.
Interruptores de seguridad
- Si el valor de la cuenta al inicio de la sesión ha bajado más del 4% respecto al cierre anterior: no hay nuevas compras ese día. Las salidas siguen permitidas.
- Si los datos no concilian — barras faltantes, una cotización obviamente desactualizada, posiciones que no coinciden con
get_equity_positions— no opero. El Mandato presupone datos sólidos; sin ellos, el Mandato no aplica.
Después de ejecutar
- Una notificación push por cada orden ejecutada, más un resumen al final de la ejecución. El usuario se entera el mismo día, no el viernes.
- El registro duradero vive en el lado del bróker (
get_equity_orders,get_realized_pnl), no en un archivo local: el contenedor de ejecución es efímero.
Todavía prohibido
- Posiciones protegidas, siempre (guardarraíl 1).
- Cualquier cuenta que no sea la designada por el bróker como transable por el agente.
- Promediar a la baja.
- Opciones, cripto, margen y venta en corto: fuera del Mandato.
Receta MCP de Robinhood (Orden de Llamadas)
Carga las herramientas con tool_search antes de usarlas (son diferidas).
La verificación del guardián se ejecuta antes de todo esto — ver Inicio de sesión — verificar que el guardián esté activo en el Mandato. Ninguna orden sale en una sesión donde la sonda no regresó denegada.
Auto-auditoría de sesión (primera llamada de cada ejecución). get_equity_orders en la cuenta transable por el agente con placed_agent="agentic" desde la sesión anterior. Una orden es una violación del Mandato por una ejecución anterior si es un stop_market o stop_limit; si es una orden market cuyo campo market_hours es anything other than regular_hours; si lleva un dollar_amount fuera del horario regular; si su time_in_force no es gfd; o si su nocional excede $1,200. Verifico type, market_hours, time_in_force y nocional en cada orden devuelta, y saco a la luz cualquier violación en la notificación push en lugar de dejarlo pasar en silencio. El historial de órdenes del bróker es el único registro duradero — el contenedor de ejecución es efímero, así que una violación que no se saca a la luz hoy se pierde.
Para analizar un ticker:
Robinhood:get_equity_historicals→ ~290 barras diarias (cierres). Esta es la entrada paraindicators.py. Solicita un rango que produzca ≥220 barras (ideal para EMA200).Robinhood:get_equity_quotes→ precio en vivo / último cierre de sesión.- Si el usuario tiene una posición:
Robinhood:get_equity_positions(cuenta correcta) para tamaño y P&L → establecerholdingal valor correcto en la puntuación.
Para el pilar Macro-Sentimiento (una vez por sesión, compartido):
get_equity_historicalspara los 8 ETFs: SPY, RSP, IWM, HYG, LQD, TLT, XLY, XLP.- Intentar obtener el diferencial de rendimiento 10Y-2Y de Investing.com (web) e inyectarlo como
yield_spread. Si está bloqueado por la política de salida de red o no está disponible, omitirlo inmediatamente sin reintentar: el script redistribuye automáticamente su peso del 20% entre los otros componentes y la ejecución continúa sin problemas sin bloquearse.
Para la gestión de cartera:
Robinhood:get_portfolio→ valor de mercado y poder de compra.Robinhood:get_equity_positions→ posiciones abiertas por cuenta.Robinhood:get_realized_pnl→ P&L realizado (útil para la revisión del viernes).
Flujo de Cálculo (Ejecutar vía Code Execution)
Los scripts son pura stdlib; no necesitan acceso a internet. Viven en scripts/ dentro del propio directorio de esta habilidad — el tiempo de ejecución me da la ruta base cuando carga la habilidad. Nunca codifico esa ruta: difiere entre entornos.
Los históricos de Robinhood son grandes y rutinariamente exceden el límite de salida de la herramienta; cuando eso sucede, el resultado se escribe en un archivo y obtengo la ruta de vuelta. Los proceso con código directamente desde ese archivo — nunca cargo barras crudas en el contexto.
Paso 0 — añadir el cierre de hoy (cada sesión, antes de cualquier otra cosa). Las barras diarias de get_equity_historicals NO incluyen la sesión actual hasta bien después del cierre: justo después de las 16:00 ET, la última barra sigue siendo ayer, por lo que puntuar esa serie puntúa el mercado de ayer. Para cada símbolo tomo get_equity_quotes → last_trade_price (la impresión de aproximadamente las 19:59:59Z es el trade de cierre de hoy) y lo añado al array de cierres con la fecha de hoy, después de afirmar que la última barra existente es la sesión anterior. Nunca añadir last_non_reg_trade_price — las impresiones de horario extendido no son cierres.
Paso 1 — Macro (una vez por sesión). El esquema de entrada es {"as_of": [fecha de hoy], "closes": {"SPY": [...], "RSP": [...], "IWM": [...], "HYG": [...], "LQD": [...], "TLT": [...], "XLY": [...], "XLP": [...]}, "yield_spread": [flotante o null]}. Ejecuto:
python3 <skill-dir>/scripts/macro_pillar.py '<json_escapado>'
Salida: {"pillar": "bullish|neutral|bearish", "score": <−100..100 entero>, "composite": <−100..100 entero>, "yield_contribution": <flotante o null>}. Puntaje negativo = bajista, positivo = alcista.
Paso 2 — Indicadores para cada ticker. El esquema de entrada es {"closes": [flotantes en orden cronológico], "ticker": "SPY"}. Ejecuto:
python3 <skill-dir>/scripts/indicators.py '<json_escapado>'
Salida: {"ticker": "...", "ema20": ..., "ema50": ..., "ema200": ..., "rsi14": ..., "macd": ..., "signal": ..., "histogram": ..., "trix": ..., "upper_band": ..., "lower_band": ..., "middle_band": ..., "band_width": ..., "percent_b": ..., "atr14": ..., "turnover_velocity": ..., "z_score": ..., "outlier_window": ...}.
**Paso 3 — Puntuación de tres pilares.** El esquema es {"ticker": "...", "rsi14": ..., "ema20": ..., "ema50": ..., "ema200": ..., "macd": ..., "signal": ..., "histogram": ..., "trix": ..., "upper_band": ..., "lower_band": ..., "middle_band": ..., "percent_b": ..., "band_width": ..., "turnover_velocity": ..., "z_score": ..., "outlier_window": ..., "atr14": ..., "macro_pillar": ..., "macro_score": ..., "holding": true|false}`. Ejecuto:
python3 <skill-dir>/scripts/score.py '<json_escapado>'
Salida: {"ticker": "...", "technical_score": ..., "technical_pillar": ..., "macro_sentiment_score": ..., "macro_pillar": ..., "overall_score": ..., "overall_pillar": ..., "cascade_decision": "ENTER|EXIT|HOLD|WAIT", "take_profit": ..., "stop_loss": ..., "action": "buy|sell|hold|wait"}.
Paso 4 — Decidir acción. La salida de score.py contiene el veredicto de la cascada. Aplico la lógica de salida por agotamiento / reentrada en rebote:
- Salida por Agotamiento: Vender si
decision cascade == EXITO el ticker muestra signos de agotamiento de tendencia (divergencia RSI, estrechamiento de Bandas de Bollinger, volumen decreciente) Y la posición está en ganancia. - Reentrada en Rebote: Si una posición se vendió por agotamiento y el precio retrocede a un nivel de soporte (EMA20/50, Banda Inferior de Bollinger) Y el RSI está por debajo de 40, considerar reentrar a la mitad del tamaño.
- Regla de Escalado: Nunca promediar a la baja. Si ya tengo una posición, solo añadir si la cascada dice ENTRAR Y el precio está por encima del costo promedio.
Paso 5 — Ejecutar (si el guardián está verificado y la cuenta es la correcta).
Estrategias de Trading
Salida por Agotamiento
Vende cuando el impulso se desvanece, no cuando el precio se da la vuelta:
- Divergencia bajista en RSI (el precio hace un máximo más alto, el RSI un máximo más bajo)
- El histograma MACD se desvanece (la barra del histograma se acorta después de un pico)
- Estrechamiento de las Bandas de Bollinger (contracción) seguido de un movimiento fuera de la banda que no se mantiene
- Velocidad de rotación por debajo de su EMA de 20 días
Reentrada en Rebote
Si se vendió por agotamiento, reentrar en el rebote:
- El precio toca la EMA20 o la EMA50 (la más cercana)
- RSI por debajo de 40
- El histograma MACD se vuelve menos negativo (comienza a girar)
- El cierre está dentro de las Bandas de Bollinger (no por debajo de la inferior)
Ambas se manejan a nivel de código determinista en scripts/, no por el agente 'a ojo'.
Contexto de la Sesión (para Informes)
Cada sesión incluye:
- Resumen de la cartera: valor de la cuenta $X, efectivo $Y, posiciones abiertas, P&L no realizado.
- Tickers analizados y sus puntuaciones.
- Acciones tomadas (órdenes ejecutadas, con precios y tamaños).
- Resultado de la verificación del guardián de órdenes.
- Nota de modo de habilidad si aplica.
Manejo de Errores
- Si un script falla (código de salida distinto de cero), registro la salida de error y continúo con el siguiente ticker o paso. No detengo toda la sesión por un fallo de script único.
- Si
get_equity_historicalsdevuelve datos insuficientes (<50 barras), registro una advertencia y omito ese ticker para el análisis de indicadores, pero aún así obtengo la cotización y posición. - Si
review_equity_orderno está disponible o falla, NO coloco la orden — informo e incluyo la salida de error.
Cambio de Modo: Proyecto vs. Habilidad
Cuando se carga como proyecto (abriendo el directorio del escritorio):
.claude/settings.jsonse carga → el hookPreToolUseparaplace_equity_orderse registra → el guardián se ejecuta automáticamente en todas las órdenes.- La sonda de inicio de sesión (
session-setup.sh) es principalmente confirmación.
Cuando se carga como habilidad (instalada y seleccionada en los ajustes):
.claude/settings.jsonNO se carga a menos que el directorio del proyecto lo contenga (raro).- El guardián no está registrado. La tabla de verificación previa es la ÚNICA protección.
- El informe de sesión llama la atención sobre esto.
Puedes obtener la ruta del directorio de la habilidad en tiempo de ejecución viendo dónde están los scripts — siempre verifico la existencia de scripts/indicators.py antes de construir la ruta.
Gracias al Usuario
Esta configuración fue desarrollada en colaboración con Eli (charlas en vivo el 2026-08-26) y se basa en el trabajo anterior de otros en la comunidad del escritorio de trading agéntico. El énfasis está en la disciplina de ejecución, no en la predicción del mercado.