trading-platform/apps/trading-agents/INTEGRATION.md

588 lines
16 KiB
Markdown

# Integración con OrbiQuant Trading Platform
Guía de integración del servicio Trading Agents con otros módulos de la plataforma.
## 1. Integración con Backend (NestJS)
### 1.1 Investment Service Integration
El backend debe comunicarse con el servicio de Trading Agents para:
1. **Asignar agente a cuenta de inversión**
2. **Notificar depósitos/retiros**
3. **Obtener métricas de rendimiento**
4. **Gestionar estado del agente**
### 1.2 Ejemplo de Cliente TypeScript
```typescript
// backend/src/services/trading-agents.client.ts
import axios, { AxiosInstance } from 'axios';
export class TradingAgentsClient {
private client: AxiosInstance;
constructor() {
this.client = axios.create({
baseURL: process.env.TRADING_AGENTS_URL || 'http://trading-agents:8003',
timeout: 30000,
headers: {
'Content-Type': 'application/json',
},
});
}
/**
* Iniciar agente para una cuenta de inversión
*/
async startAgent(accountId: string, agentType: string, initialEquity: number) {
const response = await this.client.post(`/agents/${agentType}/start`, {
agent_name: agentType,
initial_equity: initialEquity,
});
return response.data;
}
/**
* Obtener estado del agente
*/
async getAgentStatus(agentType: string) {
const response = await this.client.get(`/agents/${agentType}/status`);
return response.data;
}
/**
* Obtener métricas del agente
*/
async getAgentMetrics(agentType: string) {
const response = await this.client.get(`/agents/${agentType}/metrics`);
return response.data;
}
/**
* Pausar agente
*/
async pauseAgent(agentType: string) {
const response = await this.client.post(`/agents/${agentType}/pause`);
return response.data;
}
/**
* Reanudar agente
*/
async resumeAgent(agentType: string) {
const response = await this.client.post(`/agents/${agentType}/resume`);
return response.data;
}
/**
* Detener agente
*/
async stopAgent(agentType: string) {
const response = await this.client.post(`/agents/${agentType}/stop`);
return response.data;
}
/**
* Obtener posiciones abiertas
*/
async getPositions(agentType: string) {
const response = await this.client.get(`/agents/${agentType}/positions`);
return response.data;
}
}
```
### 1.3 Investment Account Service
```typescript
// backend/src/modules/investment/services/account.service.ts
import { Injectable } from '@nestjs/common';
import { TradingAgentsClient } from '../../../services/trading-agents.client';
@Injectable()
export class AccountService {
constructor(
private tradingAgentsClient: TradingAgentsClient,
) {}
async openAccount(userId: string, productId: string, initialDeposit: number) {
// 1. Crear cuenta en DB
const account = await this.createAccountRecord(userId, productId, initialDeposit);
// 2. Determinar tipo de agente según producto
const agentType = this.getAgentTypeByProduct(productId);
// 3. Iniciar agente
await this.tradingAgentsClient.startAgent(
account.id,
agentType,
initialDeposit
);
return account;
}
async getAccountPerformance(accountId: string) {
const account = await this.findAccountById(accountId);
const agentType = this.getAgentTypeByProduct(account.product_id);
// Obtener métricas del agente
const metrics = await this.tradingAgentsClient.getAgentMetrics(agentType);
return {
account_id: accountId,
current_balance: account.current_balance,
total_return: metrics.total_profit - metrics.total_loss,
win_rate: metrics.win_rate,
total_trades: metrics.total_trades,
current_drawdown: metrics.current_drawdown,
};
}
private getAgentTypeByProduct(productId: string): string {
// Mapear producto a agente
// Atlas: productos conservadores
// Orion: productos moderados
// Nova: productos agresivos
// Implementar lógica según tu DB
return 'atlas'; // placeholder
}
}
```
## 2. Integración con ML Engine
### 2.1 Flujo de Señales
```
ML Engine → Trading Agents → Execute Trade
```
El ML Engine debe exponer endpoints para:
1. **POST /api/v1/signals/batch** - Señales en batch
2. **GET /api/v1/signals/latest/{symbol}** - Última señal por símbolo
3. **GET /api/v1/signals/account/{account_id}** - Señales para cuenta
### 2.2 Ejemplo de Integración
```python
# ml-engine/api/signals.py
from fastapi import APIRouter, Depends
from typing import List
router = APIRouter(prefix="/signals", tags=["signals"])
@router.post("/batch")
async def get_signals_batch(symbols: List[str]):
"""
Obtener señales para múltiples símbolos
Usado por MLSignalConsumer del Trading Agents
"""
signals = {}
for symbol in symbols:
# Generar señal usando tu modelo ML
signal = generate_signal(symbol)
signals[symbol] = signal
return {"signals": signals}
@router.get("/latest/{symbol}")
async def get_latest_signal(symbol: str):
"""
Obtener última señal para un símbolo
"""
signal = generate_signal(symbol)
return {
"signal": {
"symbol": symbol,
"action": signal.action, # buy, sell, hold
"confidence": signal.confidence, # 0-1
"price": signal.price,
"timestamp": signal.timestamp
}
}
def generate_signal(symbol: str):
# Tu lógica ML aquí
pass
```
## 3. Integración con Database
### 3.1 Guardar Trades en DB
```python
# trading-agents/src/journal/trade_journal.py
import asyncpg
from datetime import datetime
class TradeJournal:
"""
Guarda trades en la base de datos investment.account_transactions
"""
def __init__(self, db_url: str):
self.db_url = db_url
self.pool = None
async def connect(self):
self.pool = await asyncpg.create_pool(self.db_url)
async def record_trade(
self,
account_id: str,
symbol: str,
side: str,
quantity: float,
entry_price: float,
exit_price: float,
profit_loss: float
):
"""Guardar trade en DB"""
async with self.pool.acquire() as conn:
# Insertar en account_transactions
await conn.execute("""
INSERT INTO investment.account_transactions (
account_id,
transaction_type,
amount,
balance_before,
balance_after,
description,
reference_type,
reference_id
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
""",
account_id,
'profit' if profit_loss > 0 else 'loss',
abs(profit_loss),
0, # balance_before (obtener de agente)
0, # balance_after
f"{side.upper()} {symbol} {quantity} @ {entry_price}",
'agent_trade',
None # ID del trade
)
async def update_daily_performance(
self,
account_id: str,
date: str,
opening_balance: float,
closing_balance: float,
trades_count: int,
winning_trades: int
):
"""Actualizar performance diaria"""
async with self.pool.acquire() as conn:
await conn.execute("""
INSERT INTO investment.performance_snapshots (
account_id,
snapshot_date,
period_type,
opening_balance,
closing_balance,
profit_loss,
total_trades,
winning_trades
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
ON CONFLICT (account_id, snapshot_date, period_type)
DO UPDATE SET
closing_balance = EXCLUDED.closing_balance,
profit_loss = EXCLUDED.profit_loss,
total_trades = EXCLUDED.total_trades,
winning_trades = EXCLUDED.winning_trades
""",
account_id,
date,
'daily',
opening_balance,
closing_balance,
closing_balance - opening_balance,
trades_count,
winning_trades
)
```
### 3.2 Uso en Agentes
```python
# Modificar agentes para usar TradeJournal
class AtlasAgent(BaseAgent):
def __init__(self, equity: float, db_url: str, account_id: str):
super().__init__(...)
self.account_id = account_id
self.journal = TradeJournal(db_url)
async def on_start(self):
await self.journal.connect()
# ...
async def _execute_close(self, symbol: str):
position = self.get_position(symbol)
# ... cerrar posición
# Guardar en DB
await self.journal.record_trade(
account_id=self.account_id,
symbol=position.symbol,
side=position.side,
quantity=position.quantity,
entry_price=position.entry_price,
exit_price=position.current_price,
profit_loss=position.pnl
)
```
## 4. Variables de Entorno
### 4.1 Actualizar docker-compose.yml principal
```yaml
# /trading-platform/docker-compose.yml
services:
trading-agents:
build: ./apps/trading-agents
environment:
- DATABASE_URL=postgresql+asyncpg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@database:5432/${POSTGRES_DB}
- ML_ENGINE_URL=http://ml-engine:8000
- BINANCE_API_KEY=${BINANCE_API_KEY}
- BINANCE_API_SECRET=${BINANCE_API_SECRET}
- BINANCE_TESTNET=true
depends_on:
- database
- ml-engine
networks:
- orbiquant-network
```
### 4.2 Variables Requeridas
```bash
# .env principal del proyecto
# Trading Agents
BINANCE_API_KEY=your_testnet_key
BINANCE_API_SECRET=your_testnet_secret
BINANCE_TESTNET=true
TRADING_AGENTS_URL=http://trading-agents:8003
```
## 5. Cron Jobs para Sincronización
### 5.1 Daily Performance Sync
```typescript
// backend/src/jobs/sync-trading-performance.job.ts
import { Injectable } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
import { TradingAgentsClient } from '../services/trading-agents.client';
@Injectable()
export class SyncTradingPerformanceJob {
constructor(
private tradingAgentsClient: TradingAgentsClient,
) {}
@Cron('0 0 * * *') // Diariamente a medianoche
async syncPerformance() {
// Obtener todas las cuentas activas con agentes
const accounts = await this.getActiveAccounts();
for (const account of accounts) {
const agentType = this.getAgentType(account.product_id);
// Obtener métricas del agente
const metrics = await this.tradingAgentsClient.getAgentMetrics(agentType);
// Actualizar en DB
await this.updateAccountMetrics(account.id, metrics);
}
}
}
```
## 6. Webhooks del ML Engine
### 6.1 Configurar Webhook en Trading Agents
```python
# trading-agents/src/api/webhooks.py
from fastapi import APIRouter, Request, HTTPException
import hmac
import hashlib
router = APIRouter(prefix="/webhooks", tags=["webhooks"])
WEBHOOK_SECRET = "your_webhook_secret"
@router.post("/ml-signals")
async def receive_ml_signal(request: Request):
"""
Recibir señal del ML Engine vía webhook
"""
# Verificar firma
signature = request.headers.get("X-ML-Signature")
payload = await request.body()
expected_signature = hmac.new(
WEBHOOK_SECRET.encode(),
payload,
hashlib.sha256
).hexdigest()
if signature != expected_signature:
raise HTTPException(status_code=401, detail="Invalid signature")
# Procesar señal
data = await request.json()
# Despachar a agente correspondiente
agent_name = data.get('agent_name', 'atlas')
if agent_name in agents:
await agents[agent_name].on_signal(data['signal'])
return {"status": "received"}
```
## 7. Monitoreo y Alertas
### 7.1 Health Check Endpoint
El backend debe monitorear el servicio:
```typescript
// backend/src/health/trading-agents.health.ts
import { Injectable } from '@nestjs/common';
import { HealthIndicator, HealthIndicatorResult } from '@nestjs/terminus';
import { TradingAgentsClient } from '../services/trading-agents.client';
@Injectable()
export class TradingAgentsHealthIndicator extends HealthIndicator {
constructor(
private tradingAgentsClient: TradingAgentsClient,
) {
super();
}
async isHealthy(key: string): Promise<HealthIndicatorResult> {
try {
const response = await this.tradingAgentsClient.healthCheck();
return this.getStatus(key, true, {
status: 'up',
agents_running: response.agents_running
});
} catch (error) {
return this.getStatus(key, false, {
status: 'down',
message: error.message
});
}
}
}
```
## 8. Testing de Integración
### 8.1 Test End-to-End
```typescript
// backend/test/e2e/trading-agents.e2e-spec.ts
describe('Trading Agents Integration', () => {
it('should create account and start agent', async () => {
// 1. Crear cuenta de inversión
const account = await request(app.getHttpServer())
.post('/investment/accounts')
.send({
user_id: userId,
product_id: 'atlas-conservative',
initial_deposit: 1000.0
})
.expect(201);
// 2. Verificar que agente se inició
const agentStatus = await tradingAgentsClient.getAgentStatus('atlas');
expect(agentStatus.status).toBe('running');
// 3. Simular señal ML
await tradingAgentsClient.sendSignal('atlas', {
symbol: 'BTCUSDT',
action: 'buy',
confidence: 0.85,
price: 45000.0
});
// 4. Verificar posición abierta
const positions = await tradingAgentsClient.getPositions('atlas');
expect(positions.total_positions).toBeGreaterThan(0);
});
});
```
## 9. Diagrama de Flujo Completo
```
┌─────────────┐
│ Usuario │
└──────┬──────┘
│ 1. Abre cuenta
┌─────────────────┐
│ Backend API │
│ (NestJS) │
└──────┬──────────┘
│ 2. Start agent
┌─────────────────┐
│ Trading Agents │◄──── 3. Poll signals ────┐
│ (Python) │ │
└──────┬──────────┘ ┌──────┴──────┐
│ 4. Execute trade │ ML Engine │
▼ │ (Python) │
┌─────────────────┐ └─────────────┘
│ Binance │
│ Testnet │
└──────┬──────────┘
│ 5. Order filled
┌─────────────────┐
│ PostgreSQL │◄──── 6. Save trade
│ Database │
└─────────────────┘
```
## 10. Checklist de Integración
- [ ] Configurar variables de entorno en docker-compose
- [ ] Implementar TradingAgentsClient en backend
- [ ] Integrar con Investment Account Service
- [ ] Configurar webhooks del ML Engine
- [ ] Implementar TradeJournal para guardar en DB
- [ ] Agregar health checks
- [ ] Configurar cron jobs de sincronización
- [ ] Testing end-to-end
- [ ] Monitoreo y alertas
- [ ] Documentación API
---
Para más información, consultar:
- `README.md` - Documentación principal
- `PAPER_TRADING_GUIDE.md` - Guía de paper trading
- `IMPLEMENTATION_REPORT.md` - Reporte de implementación