How I Built a Multi-Chain DEX Trading Bot with Hermes Agent as My Trading Partner A developer built IYOP Trading Bot, an AI-powered multi-chain DEX trading bot that executes trades across Solana (Jupiter), Ethereum (Uniswap V3), and BSC (PancakeSwap V2). The bot uses MiMo v2 for market analysis, generates signals from multiple technical indicators, and manages risk with position sizing and drawdown protection, running as a FastAPI backend with a web dashboard. This is a submission for the Hermes Agent Challenge: Build With Hermes Agent IYOP Trading Bot is an AI-powered multi-chain DEX trading bot that executes trades across Solana Jupiter , Ethereum Uniswap V3 , and BSC PancakeSwap V2 . It uses MiMo v2 for market analysis, generates signals from multiple technical indicators, and manages risk with position sizing and drawdown protection. The problem I was solving: decentralized trading is fragmented. Each chain has its own DEX, its own quirks, its own liquidity pools. Monitoring them manually is impossible. Executing trades across chains requires different SDKs, different gas management, different wallet handling. I needed a unified layer that could: And I needed Hermes Agent to make the development process fast enough to actually ship. Live Demo: iyop-trading-terminal.vercel.app https://iyop-trading-terminal.vercel.app Source: github.com/iyop666/iyop-trading-bot https://github.com/iyop666/iyop-trading-bot The bot runs as a FastAPI backend with a web dashboard. Key features: Here are the core modules that Hermes Agent helped build: The analyzer connects to IYOP v2 for fast market analysis, signal generation, and sentiment analysis: python import httpx from dataclasses import dataclass from enum import Enum MIMO API URL = "http://127.0.0.1:19911/v1/chat/completions" MIMO MODEL = "gitlawb/mimo-v2-flash" class Signal Enum : BUY = "buy" SELL = "sell" HOLD = "hold" @dataclass class MarketAnalysis: signal: Signal confidence: float reasoning: str risk level: str async def analyze market pair: str, timeframe: str - MarketAnalysis: """Send market data to MiMo v2 for analysis.""" async with httpx.AsyncClient as client: response = await client.post MIMO API URL, json={ "model": MIMO MODEL, "messages": {"role": "system", "content": "Analyze this trading pair..."}, {"role": "user", "content": f"Pair: {pair}, Timeframe: {timeframe}"} , "temperature": 0.1 }, timeout=30 result = response.json return parse analysis result Combines multiple technical indicators with weighted scoring: python from dataclasses import dataclass from enum import Enum class SignalType Enum : STRONG BUY = "strong buy" BUY = "buy" WEAK BUY = "weak buy" HOLD = "hold" WEAK SELL = "weak sell" SELL = "sell" STRONG SELL = "strong sell" @dataclass class TradeSignal: signal type: SignalType confidence: float 0.0 to 1.0 pair: str price: float indicators: dict reasoning: str def generate signal indicators: dict, ai analysis: dict - TradeSignal: """Combine technical indicators with AI analysis.""" weights = { "rsi": 0.25, "macd": 0.20, "bollinger": 0.15, "volume": 0.15, "ai analysis": 0.25 } score = 0.0 for indicator, weight in weights.items : score += normalize indicators.get indicator, 0 weight signal type = classify signal score return TradeSignal signal type=signal type, confidence=abs score , pair=indicators "pair" , price=indicators "price" , indicators=indicators, reasoning=build reasoning indicators, ai analysis Unified interface for Jupiter, Uniswap V3, and PancakeSwap: python from enum import Enum import httpx class DEX Enum : JUPITER = "jupiter" Solana UNISWAP = "uniswap" Ethereum PANCAKESWAP = "pancakeswap" BSC class Chain Enum : SOLANA = "solana" ETHEREUM = "ethereum" BSC = "bsc" @dataclass class SwapResult: success: bool tx hash: str input amount: float output amount: float chain: Chain dex: DEX gas used: float async def execute swap dex: DEX, chain: Chain, token in: str, token out: str, amount: float, slippage: float = 0.5 - SwapResult: """Execute a swap on the specified DEX.""" if dex == DEX.JUPITER: return await jupiter swap token in, token out, amount, slippage elif dex == DEX.UNISWAP: return await uniswap swap token in, token out, amount, slippage elif dex == DEX.PANCAKESWAP: return await pancakeswap swap token in, token out, amount, slippage Position sizing and drawdown protection: @dataclass class RiskManager: max position pct: float = 0.1 10% max per position max daily loss: float = 0.05 5% max daily loss max drawdown: float = 0.15 15% max drawdown current drawdown: float = 0.0 daily pnl: float = 0.0 def can open position self, portfolio value: float, position size: float - bool: """Check if a new position is within risk limits.""" Check position size limit if position size / portfolio value self.max position pct: return False Check daily loss limit if self.daily pnl < - portfolio value self.max daily loss : return False Check drawdown limit if self.current drawdown self.max drawdown: return False return True def calculate position size self, portfolio value: float, entry price: float, stop loss: float - float: """Calculate optimal position size based on risk parameters.""" risk per trade = portfolio value self.max position pct price risk = abs entry price - stop loss / entry price return risk per trade / price risk if price risk 0 else 0 Handles order lifecycle with stop-loss and take-profit: class Side str, Enum : BUY = "buy" SELL = "sell" class OrderStatus str, Enum : PENDING = "pending" FILLED = "filled" CANCELLED = "cancelled" SL HIT = "stop loss hit" TP HIT = "take profit hit" @dataclass class Position: id: str pair: str side: Side entry price: float current price: float size: float stop loss: float take profit: float pnl: float chain: Chain dex: DEX class Trader: def init self, risk manager: RiskManager : self.positions: dict str, Position = {} self.risk manager = risk manager self.trade history: list dict = async def open position self, pair: str, side: Side, size: float, stop loss: float, take profit: float, chain: Chain, dex: DEX - Position: """Open a new position with risk checks.""" if not self.risk manager.can open position self.portfolio value, size : raise RiskLimitExceeded "Position exceeds risk limits" Execute the swap result = await execute swap dex, chain, pair, size position = Position id=str uuid.uuid4 , pair=pair, side=side, entry price=result.price, current price=result.price, size=size, stop loss=stop loss, take profit=take profit, pnl=0.0, chain=chain, dex=dex self.positions position.id = position return position When I started building the trading bot, I described the requirements to Hermes: "I need a multi-chain DEX trading bot with AI analysis, signal generation, risk management, and trade execution. It should support Jupiter, Uniswap V3, and PancakeSwap." Hermes designed the module structure: backend/ai/ for AI analysis and signal generation backend/core/ for DEX integration, risk management, and trade executionThat architecture saved me hours of refactoring later. Each DEX has different APIs, different transaction formats, different gas estimation. Instead of reading docs for each one, I told Hermes: "Write async swap functions for Jupiter, Uniswap V3, and PancakeSwap. Use httpx, handle errors, return transaction hashes." Hermes generated the integration code for all three DEXs. I reviewed the error handling, adjusted the slippage parameters, and tested. What would have taken a full day of reading docs and writing boilerplate took 30 minutes. The risk manager needed to handle position sizing, drawdown limits, and daily loss caps. I described the rules: "Max 10% per position, max 5% daily loss, max 15% drawdown. Calculate position size based on stop-loss distance." Hermes implemented the logic with proper edge cases. When I tested it with extreme values 100% loss scenarios , it correctly rejected the trades. Combining multiple indicators into a single signal required a weighting system. I asked Hermes: "Create a signal generator that weights RSI 25% , MACD 20% , Bollinger 15% , Volume 15% , and AI analysis 25% . Normalize each to -1 to +1 range." Hermes built the weighted scoring system with configurable weights. I later adjusted the AI analysis weight to 30% after testing showed it was the most predictive. When the bot was not executing trades correctly, I asked Hermes to trace the issue: "Trades are not executing. Check the swap function, the risk manager, and the trade executor. Find the bottleneck." Hermes read through the code, found that the risk manager was rejecting trades because the portfolio value was not being updated after each trade. One line fix, but finding it manually would have taken an hour of debugging. Building a trading bot requires: Hermes handled all of these because it maintained context across the entire codebase. When I changed the risk manager, it automatically suggested updates to the trader. When I added a new DEX, it updated the signal generator to include the new chain. That cross-module awareness is what made the difference between a prototype and a working bot. Project Stats: Links: