- Configure workspace Git repository with comprehensive .gitignore - Add Odoo as submodule for ERP reference code - Include documentation: SETUP.md, GIT-STRUCTURE.md - Add gitignore templates for projects (backend, frontend, database) - Structure supports independent repos per project/subproject level Workspace includes: - core/ - Reusable patterns, modules, orchestration system - projects/ - Active projects (erp-suite, gamilit, trading-platform, etc.) - knowledge-base/ - Reference code and patterns (includes Odoo submodule) - devtools/ - Development tools and templates - customers/ - Client implementations template 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
16 KiB
16 KiB
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:
- Asignar agente a cuenta de inversión
- Notificar depósitos/retiros
- Obtener métricas de rendimiento
- Gestionar estado del agente
1.2 Ejemplo de Cliente 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
// 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:
- POST /api/v1/signals/batch - Señales en batch
- GET /api/v1/signals/latest/{symbol} - Última señal por símbolo
- GET /api/v1/signals/account/{account_id} - Señales para cuenta
2.2 Ejemplo de Integración
# 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
# 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
# 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
# /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
# .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
// 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
# 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:
// 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
// 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 principalPAPER_TRADING_GUIDE.md- Guía de paper tradingIMPLEMENTATION_REPORT.md- Reporte de implementación