Estructura del sistema
Principio de diseño: la estrategia y las reglas de riesgo son funciones puras que se prueban sin
red ni base de datos. Todo lo que habla con Alpaca vive en dos sitios (broker/ y data/ingest.py)
detrás de interfaces con implementaciones falsas para tests. El panel web muestra a la derecha el
árbol real de src/trading_bot, leído del disco.
Componentes
| Componente | Módulo | Responsabilidad |
|---|---|---|
| Configuración | config.py |
Variables de entorno, parámetros, bloqueo del modo live |
| Bróker | broker/ |
base.py interfaz, alpaca_client.py real, fake_client.py para tests |
| Datos | data/ingest.py, data/indicators.py |
Descarga con caché CSV; SMA, EMA, ATR, RSI en pandas |
| Estrategia | strategy/ |
Signal(BUY/SELL/HOLD, reason) a partir de un DataFrame |
| Riesgo | risk/rules.py, risk/manager.py |
Reglas puras y el gestor que produce OrderIntent o Rejection |
| Ejecución | execution/executor.py, execution/lifecycle.py, execution/sync.py |
Entradas bracket, salidas que cancelan patas, máquina de estados de posición y sincronización de fills; modo DRY_RUN |
| Ciclo | engine/cycle.py |
Orquesta un ciclo completo y escribe la bitácora |
| Scheduler | engine/scheduler.py |
Ejecución 9:35 ET, sincronización de órdenes cada hora, snapshot 16:10, resumen 16:15 (Fase 2) |
| Backtest | backtest/engine.py, backtest/portfolio.py, backtest/report.py |
Simulación barra a barra por símbolo y de cartera, con la misma estrategia y sizing |
| Notificaciones | notify/ |
Telegram (Fase 2) |
| Web | web/ |
Panel operativo y documentación viva (FastAPI + Jinja2) |
| Persistencia | models.py, db.py |
SQLite vía SQLModel; kill switch en BD o archivo KILL |
| CLI | cli.py |
`bot status |
Flujo de un ciclo
reloj de mercado (Alpaca) ─► ¿abierto? ─no─► fin
│ sí
▼
barras diarias (caché + Alpaca) ─► strategy.evaluate() ─► Signal
▼
RiskManager.validate(signal, cuenta, posiciones, contexto) ─► OrderIntent | Rejection
▼
OrderExecutor.submit(intent) ─► Alpaca (o DRY_RUN) ─► decision_log + orders
▼
notificación (Telegram) y heartbeat
Si un símbolo falla, se registra con risk_status=error y se continúa con el siguiente. Nunca se
reintenta el envío de una orden dentro del mismo ciclo: evitar duplicados vale más que una orden
perdida.
Tablas
| Tabla | Contenido |
|---|---|
decision_log |
Una fila por evaluación: señal, motivo, veredicto de riesgo, orden asociada |
orders |
Órdenes enviadas y sus patas, con fills sincronizados desde el bróker |
positions |
Ciclo de vida: SIGNALED → SUBMITTED → OPEN → EXITING → CLOSED (o REJECTED / CANCELLED), con motivo de salida y marca de day trade |
equity_snapshots |
Equity, cash y nº de posiciones al cierre de cada día |
journal_notes |
Notas manuales; las etiquetadas mejora:* alimentan la página de Mejoras |
watchlist |
Símbolos en seguimiento |
settings_runtime |
Flags mutables: kill switch manual, kill_until (kill diario), heartbeat, pico de equity |
Modos
| Modo | ALPACA_PAPER |
DRY_RUN |
Qué hace |
|---|---|---|---|
| DRY_RUN | true | true | Evalúa y registra; no envía órdenes. Por defecto. |
| PAPER | true | false | Envía órdenes a la cuenta simulada. |
| LIVE | false | false | Dinero real. Exige I_UNDERSTAND_LIVE_TRADING=true. Fase 6. |
Fuente: docs/ARCHITECTURE.md · modificado hace 0 min. Se lee del disco en cada carga: git pull lo actualiza sin reiniciar.