AI 交易代理以太坊開發完整指南:從智慧合約到機器人實作
本文深入探討如何在以太坊生態系統中構建 AI 交易代理,涵蓋智慧合約開發、策略實現、風險控制、與 DeFi 協議交互等多個維度。提供完整的 Solidity 智慧合約範例和 TypeScript 交易機器人代碼,幫助開發者構建 24/7 自動化交易系統。文章涵蓋訂單管理、風險管理、機器學習策略、信號產生、訂單執行和即時監控等完整模組。
AI 交易代理以太坊開發完整指南:從智慧合約到機器人實作
概述
人工智慧與區塊鏈技術的結合正在催生一個全新的金融科技領域。AI 交易代理(Trading Bot)能夠自動分析市場數據、執行交易策略、管理風險,為投資者提供 24/7 的自動化交易服務。本文深入探討如何在以太坊生態系統中構建 AI 交易代理,涵蓋智慧合約開發、策略實現、風險控制、與 DeFi 協議交互等多個維度,提供完整的程式碼範例和實作指導。
本文假定讀者具備基本的 Solidity 開發經驗和 JavaScript/TypeScript 程式設計能力,對 DeFi 協議有基本理解。所有程式碼均基於 Solidity 0.8.x 和 ethers.js v6 版本,可直接在專案中使用。
第一章:AI 交易代理架構設計
1.1 系統架構概述
AI 交易代理的完整系統架構包含多個核心組件,每個組件負責不同的功能模組。
系統架構圖:
AI 交易代理系統架構:
┌─────────────────────────────────────────────────────────────────────────┐
│ 數據層 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 價格數據 │ │ 鏈上數據 │ │ 社交數據 │ │ 新聞數據 │ │
│ │ Price Feed │ │ On-chain │ │ Social │ │ News │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
└─────────┼────────────────┼────────────────┼────────────────┼────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 分析層 │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ AI 策略引擎 │ │
│ │ • 機器學習模型推理 │ │
│ │ • 技術指標計算 │ │
│ │ • 訊號產生 │ │
│ │ • 倉位管理 │ │
│ └────────────────────────────┬────────────────────────────────────┘ │
└───────────────────────────────┼─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 執行層 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 訂單管理 │ │ 風險檢查 │ │ 交易執行 │ │ 監控告警 │ │
│ │ Order Mgr │ │ Risk Check │ │ Executor │ │ Monitor │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
└─────────┼────────────────┼────────────────┼────────────────┼────────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ 區塊鏈層 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 錢包/私鑰 │ │ RPC 節點 │ │ DeFi 協議 │ │ 區塊瀏覽器 │ │
│ │ Wallet │ │ RPC Node │ │ Protocols │ │ Explorer │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
1.2 核心組件設計
訂單管理模組:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title OrderManager
* @dev AI 交易代理訂單管理合約
*/
contract OrderManager {
// 訂單類型
enum OrderType {
Market, // 市價單
Limit, // 限價單
StopLoss, // 止損單
TakeProfit // 止盈單
}
// 訂單狀態
enum OrderStatus {
Pending, // 待執行
Executed, // 已執行
Cancelled, // 已取消
Expired // 已過期
}
// 訂單結構
struct Order {
bytes32 orderId;
address owner;
OrderType orderType;
address inputToken;
address outputToken;
uint256 inputAmount;
uint256 price; // 限價/止損/止盈價格
uint256 stopLossPrice;
uint256 takeProfitPrice;
uint256 deadline;
OrderStatus status;
uint256 filledAmount;
uint256 createdAt;
}
// 狀態變量
mapping(bytes32 => Order) public orders;
mapping(address => bytes32[]) public userOrders;
address public priceOracle;
uint256 public maxSlippage = 300; // 3%
// 事件
event OrderCreated(bytes32 indexed orderId, address indexed owner);
event OrderExecuted(bytes32 indexed orderId, uint256 inputAmount, uint256 outputAmount);
event OrderCancelled(bytes32 indexed orderId);
/**
* @dev 創建市價單
*/
function createMarketOrder(
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 deadline
) external returns (bytes32 orderId) {
require(inputAmount > 0, "Invalid amount");
require(deadline > block.timestamp, "Invalid deadline");
orderId = keccak256(abi.encode(
msg.sender,
inputToken,
outputToken,
inputAmount,
block.timestamp
));
orders[orderId] = Order({
orderId: orderId,
owner: msg.sender,
orderType: OrderType.Market,
inputToken: inputToken,
outputToken: outputToken,
inputAmount: inputAmount,
price: 0,
stopLossPrice: 0,
takeProfitPrice: 0,
deadline: deadline,
status: OrderStatus.Pending,
filledAmount: 0,
createdAt: block.timestamp
});
userOrders[msg.sender].push(orderId);
emit OrderCreated(orderId, msg.sender);
}
/**
* @dev 創建限價單
*/
function createLimitOrder(
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 limitPrice,
uint256 deadline
) external returns (bytes32 orderId) {
require(inputAmount > 0, "Invalid amount");
require(limitPrice > 0, "Invalid price");
require(deadline > block.timestamp, "Invalid deadline");
orderId = keccak256(abi.encode(
msg.sender,
inputToken,
outputToken,
inputAmount,
limitPrice,
block.timestamp
));
orders[orderId] = Order({
orderId: orderId,
owner: msg.sender,
orderType: OrderType.Limit,
inputToken: inputToken,
outputToken: outputToken,
inputAmount: inputAmount,
price: limitPrice,
stopLossPrice: 0,
takeProfitPrice: 0,
deadline: deadline,
status: OrderStatus.Pending,
filledAmount: 0,
createdAt: block.timestamp
});
userOrders[msg.sender].push(orderId);
emit OrderCreated(orderId, msg.sender);
}
/**
* @dev 創建止損單
*/
function createStopLossOrder(
address inputToken,
address outputToken,
uint256 inputAmount,
uint256 stopLossPrice,
uint256 deadline
) external returns (bytes32 orderId) {
require(inputAmount > 0, "Invalid amount");
require(stopLossPrice > 0, "Invalid stop loss price");
orderId = keccak256(abi.encode(
msg.sender,
inputToken,
outputToken,
inputAmount,
stopLossPrice,
block.timestamp
));
orders[orderId] = Order({
orderId: orderId,
owner: msg.sender,
orderType: OrderType.StopLoss,
inputToken: inputToken,
outputToken: outputToken,
inputAmount: inputAmount,
price: 0,
stopLossPrice: stopLossPrice,
takeProfitPrice: 0,
deadline: deadline,
status: OrderStatus.Pending,
filledAmount: 0,
createdAt: block.timestamp
});
userOrders[msg.sender].push(orderId);
emit OrderCreated(orderId, msg.sender);
}
/**
* @dev 取消訂單
*/
function cancelOrder(bytes32 orderId) external {
Order storage order = orders[orderId];
require(order.owner == msg.sender, "Not owner");
require(order.status == OrderStatus.Pending, "Order not pending");
order.status = OrderStatus.Cancelled;
emit OrderCancelled(orderId);
}
/**
* @dev 查詢訂單
*/
function getOrder(bytes32 orderId) external view returns (Order memory) {
return orders[orderId];
}
/**
* @dev 批量查詢訂單
*/
function getOrders(bytes32[] calldata orderIds)
external
view
returns (Order[] memory)
{
Order[] memory result = new Order[](orderIds.length);
for (uint256 i = 0; i < orderIds.length; i++) {
result[i] = orders[orderIds[i]];
}
return result;
}
}
1.3 風險控制模組
風險管理合約:
/**
* @title RiskManager
* @dev AI 交易代理風險控制合約
*/
contract RiskManager {
// 風險參數
struct RiskParams {
uint256 maxPositionSize; // 最大倉位規模
uint256 maxDailyLoss; // 每日最大虧損
uint256 maxDrawdown; // 最大回撤
uint256 maxLeverage; // 最大槓桿
uint256 minPositionSize; // 最小倉位規模
uint256 maxSlippage; // 最大滑點
}
// 風險狀態
struct RiskState {
uint256 dailyVolume; // 今日交易量
uint256 dailyProfitLoss; // 今日損益
uint256 peakBalance; // 歷史最高餘額
uint256 lastResetTime; // 上次重置時間
uint256 consecutiveLosses; // 連續虧損次數
}
// 狀態變量
RiskParams public params;
RiskState public state;
address public owner;
// 事件
event RiskLimitTriggered(string reason, uint256 value);
event PositionOpened(uint256 size);
event PositionClosed(uint256 size, uint256 pnl);
constructor() {
owner = msg.sender;
params = RiskParams({
maxPositionSize: 100e18, // 100 ETH
maxDailyLoss: 10e18, // 10 ETH
maxDrawdown: 2000, // 20%
maxLeverage: 3, // 3x
minPositionSize: 0.1e18, // 0.1 ETH
maxSlippage: 300 // 3%
});
state.peakBalance = address(this).balance;
}
/**
* @dev 檢查交易前風險
*/
function checkPreTrade(uint256 size, uint256 slippage)
external
view
returns (bool allowed, string memory reason)
{
// 檢查倉位規模
if (size < params.minPositionSize) {
return (false, "Position too small");
}
if (size > params.maxPositionSize) {
return (false, "Position too large");
}
// 檢查滑點
if (slippage > params.maxSlippage) {
return (false, "Slippage too high");
}
// 檢查每日虧損限額
if (state.dailyProfitLoss > params.maxDailyLoss) {
return (false, "Daily loss limit exceeded");
}
// 檢查回撤
uint256 currentBalance = address(this).balance;
if (state.peakBalance > 0) {
uint256 drawdown = ((state.peakBalance - currentBalance) * 10000) / state.peakBalance;
if (drawdown > params.maxDrawdown) {
return (false, "Max drawdown exceeded");
}
}
return (true, "");
}
/**
* @dev 記錄交易
*/
function recordTrade(uint256 size, uint256 pnl) external {
require(msg.sender == owner, "Not authorized");
state.dailyVolume += size;
state.dailyProfitLoss += int256(pnl);
state.consecutiveLosses = pnl > 0 ? 0 : state.consecutiveLosses + 1;
// 更新歷史最高餘額
uint256 currentBalance = address(this).balance;
if (currentBalance > state.peakBalance) {
state.peakBalance = currentBalance;
}
// 重置每日統計(如果超過 24 小時)
if (block.timestamp - state.lastResetTime > 24 hours) {
state.dailyVolume = 0;
state.dailyProfitLoss = 0;
state.lastResetTime = block.timestamp;
}
emit PositionOpened(size);
if (pnl != 0) {
emit PositionClosed(size, uint256(int256(pnl) >= 0 ? 1 : 0));
}
}
/**
* @dev 獲取風險評分
*/
function getRiskScore() external view returns (uint256 score) {
uint256 currentBalance = address(this).balance;
score = 50; // 基礎分數
// 根據回撤調整
if (state.peakBalance > 0) {
uint256 drawdown = ((state.peakBalance - currentBalance) * 10000) / state.peakBalance;
if (drawdown > 1500) score += 30; // >15% 回撤
else if (drawdown > 1000) score += 20;
else if (drawdown > 500) score += 10;
}
// 根據連續虧損調整
if (state.consecutiveLosses >= 5) score += 20;
else if (state.consecutiveLosses >= 3) score += 10;
return score;
}
/**
* @dev 更新風險參數
*/
function updateRiskParams(RiskParams memory _params) external {
require(msg.sender == owner, "Not authorized");
params = _params;
}
}
第二章:策略實現與機器人開發
2.1 TypeScript 交易機器人框架
完整交易機器人代碼:
// trading-bot.ts - AI 交易機器人實現
import { ethers, BigNumber } from 'ethers';
import { Contract, Wallet, providers } from 'ethers';
import axios from 'axios';
// 類型定義
interface TradingConfig {
rpcUrl: string;
privateKey: string;
maxSlippage: number;
minTradeAmount: BigNumber;
maxTradeAmount: BigNumber;
pollingInterval: number;
}
interface MarketData {
price: number;
volume: number;
timestamp: number;
bid: number;
ask: number;
}
interface TradingSignal {
action: 'BUY' | 'SELL' | 'HOLD';
confidence: number;
price: number;
size: BigNumber;
reason: string;
}
// ERC20 代幣 ABI
const ERC20_ABI = [
'function approve(address spender, uint256 amount) returns (bool)',
'function allowance(address owner, address spender) view returns (uint256)',
'function balanceOf(address account) view returns (uint256)',
'function transfer(address to, uint256 amount) returns (bool)'
];
// Uniswap V3 Router ABI
const UNISWAP_ROUTER_ABI = [
'function exactInputSingle((address tokenIn, address tokenOut, uint24 fee, address recipient, uint256 deadline, uint256 amountIn, uint256 amountOutMinimum, uint160 sqrtPriceLimitX96)) external payable returns (uint256 amountOut)'
];
/**
* AI 交易機器人類
*/
class AITradingBot {
private provider: providers.JsonRpcProvider;
private wallet: Wallet;
private config: TradingConfig;
private isRunning: boolean = false;
private position: BigNumber = BigNumber.from(0);
private entryPrice: number = 0;
// 合約地址
private readonly WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
private readonly USDC = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
private readonly UNISWAP_ROUTER = '0xE592427A0AEce92De3Edee1F18E0157C05861564';
constructor(config: TradingConfig) {
this.config = config;
this.provider = new providers.JsonRpcProvider(config.rpcUrl);
this.wallet = new Wallet(config.privateKey, this.provider);
}
/**
* 啟動交易機器人
*/
async start(): Promise<void> {
console.log('🤖 AI Trading Bot starting...');
this.isRunning = true;
await this.mainLoop();
}
/**
* 停止交易機器人
*/
stop(): void {
console.log('🛑 AI Trading Bot stopping...');
this.isRunning = false;
}
/**
* 主循環
*/
private async mainLoop(): Promise<void> {
while (this.isRunning) {
try {
// 1. 獲取市場數據
const marketData = await this.fetchMarketData();
// 2. 生成交易訊號
const signal = await this.generateSignal(marketData);
// 3. 執行交易
if (signal.action !== 'HOLD') {
await this.executeTrade(signal);
}
// 4. 監控倉位
await this.monitorPosition(marketData);
} catch (error) {
console.error('Error in main loop:', error);
}
// 等待下次輪詢
await this.sleep(this.config.pollingInterval);
}
}
/**
* 獲取市場數據
*/
private async fetchMarketData(): Promise<MarketData> {
// 從多個來源獲取價格數據
const [priceData, volumeData] = await Promise.all([
this.getPriceFromUniswap(),
this.getVolumeFromDEX()
]);
return {
price: priceData,
volume: volumeData,
timestamp: Date.now(),
bid: priceData * 0.9995, // 買入價
ask: priceData * 1.0005 // 賣出價
};
}
/**
* 從 Uniswap 獲取價格
*/
private async getPriceFromUniswap(): Promise<number> {
const provider = this.provider;
// 使用合約 call 獲取價格(簡化版)
// 實際應使用 subgraph 或價格預言機
const response = await axios.get('https://api.coingecko.com/api/v3/simple/price', {
params: {
ids: 'ethereum',
vs_currencies: 'usd'
}
});
return response.data.ethereum.usd;
}
/**
* 獲取交易量
*/
private async getVolumeFromDEX(): Promise<number> {
// 從 DEX 獲取 24 小時交易量
// 實際應使用 The Graph 或DEX API
return 1_000_000_000; // 簡化返回值
}
/**
* 生成交易訊號(AI 策略)
*/
private async generateSignal(marketData: MarketData): Promise<TradingSignal> {
// 簡化的 AI 策略邏輯
// 實際應使用機器學習模型
const indicators = await this.calculateIndicators(marketData);
// 簡單的均值回歸策略
const movingAverage = indicators.movingAverage;
const currentPrice = marketData.price;
let action: 'BUY' | 'SELL' | 'HOLD' = 'HOLD';
let confidence = 0;
let reason = '';
if (currentPrice < movingAverage * 0.95) {
// 價格低於均值,買入
action = 'BUY';
confidence = Math.min(90, ((movingAverage - currentPrice) / movingAverage) * 200);
reason = `Price ${currentPrice} below MA ${movingAverage}`;
} else if (currentPrice > movingAverage * 1.05) {
// 價格高於均值,賣出
action = 'SELL';
confidence = Math.min(90, ((currentPrice - movingAverage) / movingAverage) * 200);
reason = `Price ${currentPrice} above MA ${movingAverage}`;
}
// 根據 RSI 調整訊號
if (indicators.rsi < 30 && action === 'HOLD') {
action = 'BUY';
confidence = 70;
reason = 'RSI oversold';
} else if (indicators.rsi > 70 && action === 'HOLD') {
action = 'SELL';
confidence = 70;
reason = 'RSI overbought';
}
// 計算交易大小
const balance = await this.provider.getBalance(this.wallet.address);
const tradeSize = balance.div(10); // 使用 10% 的餘額
return {
action,
confidence,
price: currentPrice,
size: tradeSize,
reason
};
}
/**
* 計算技術指標
*/
private async calculateIndicators(marketData: MarketData): Promise<{
movingAverage: number;
rsi: number;
macd: number;
}> {
// 獲取歷史價格數據
const prices = await this.getHistoricalPrices(20);
// 計算簡單移動平均
const sum = prices.reduce((a, b) => a + b, 0);
const movingAverage = sum / prices.length;
// 計算 RSI
const rsi = this.calculateRSI(prices);
// 計算 MACD
const macd = this.calculateMACD(prices);
return { movingAverage, rsi, macd };
}
/**
* 獲取歷史價格
*/
private async getHistoricalPrices(days: number): Promise<number[]> {
// 從 API 獲取歷史價格
// 這裡返回模擬數據
const prices: number[] = [];
let price = 2000;
for (let i = 0; i < days; i++) {
price += (Math.random() - 0.5) * 100;
prices.push(price);
}
return prices;
}
/**
* 計算 RSI
*/
private calculateRSI(prices: number[]): number {
if (prices.length < 2) return 50;
let gains = 0;
let losses = 0;
for (let i = 1; i < prices.length; i++) {
const change = prices[i] - prices[i - 1];
if (change > 0) gains += change;
else losses -= change;
}
const avgGain = gains / (prices.length - 1);
const avgLoss = losses / (prices.length - 1);
if (avgLoss === 0) return 100;
const rs = avgGain / avgLoss;
return 100 - (100 / (1 + rs));
}
/**
* 計算 MACD
*/
private calculateMACD(prices: number[]): number {
if (prices.length < 26) return 0;
// 簡化的 MACD 計算
const ema12 = this.calculateEMA(prices, 12);
const ema26 = this.calculateEMA(prices, 26);
return ema12 - ema26;
}
/**
* 計算 EMA
*/
private calculateEMA(prices: number[], period: number): number {
if (prices.length < period) return prices[prices.length - 1];
const multiplier = 2 / (period + 1);
let ema = prices[0];
for (let i = 1; i < prices.length; i++) {
ema = (prices[i] - ema) * multiplier + ema;
}
return ema;
}
/**
* 執行交易
*/
private async executeTrade(signal: TradingSignal): Promise<void> {
console.log(`\n📊 Trading Signal: ${signal.action}`);
console.log(` Confidence: ${signal.confidence.toFixed(2)}%`);
console.log(` Size: ${ethers.utils.formatEther(signal.size)} ETH`);
console.log(` Reason: ${signal.reason}`);
// 風險檢查
const riskCheck = await this.checkRisk(signal);
if (!riskCheck.allowed) {
console.log(` ⚠️ Risk check failed: ${riskCheck.reason}`);
return;
}
try {
if (signal.action === 'BUY') {
await this.executeBuy(signal);
} else if (signal.action === 'SELL') {
await this.executeSell(signal);
}
} catch (error) {
console.error('Trade execution failed:', error);
}
}
/**
* 執行買入
*/
private async executeBuy(signal: TradingSignal): Promise<void> {
const router = new Contract(
this.UNISWAP_ROUTER,
UNISWAP_ROUTER_ABI,
this.wallet
);
const amountOutMin = signal.size
.mul(95) // 5% 滑點容忍
.div(100);
const tx = await router.exactInputSingle({
tokenIn: this.WETH,
tokenOut: this.USDC,
fee: 3000,
recipient: this.wallet.address,
deadline: Math.floor(Date.now() / 1000) + 600,
amountIn: signal.size,
amountOutMinimum: amountOutMin,
sqrtPriceLimitX96: 0
});
console.log(` 📝 Transaction sent: ${tx.hash}`);
await tx.wait();
console.log(` ✅ Trade confirmed!`);
this.position = this.position.add(signal.size);
this.entryPrice = signal.price;
}
/**
* 執行賣出
*/
private async executeSell(signal: TradingSignal): Promise<void> {
// 類似買入邏輯,方向相反
console.log(` 📤 Executing SELL order...`);
// 更新倉位
this.position = this.position.sub(signal.size);
}
/**
* 風險檢查
*/
private async checkRisk(signal: TradingSignal): Promise<{allowed: boolean; reason: string}> {
// 檢查交易大小
if (signal.size.lt(this.config.minTradeAmount)) {
return { allowed: false, reason: 'Below minimum trade size' };
}
if (signal.size.gt(this.config.maxTradeAmount)) {
return { allowed: false, reason: 'Above maximum trade size' };
}
// 檢查信心度
if (signal.confidence < 60) {
return { allowed: false, reason: 'Low confidence' };
}
return { allowed: true, reason: '' };
}
/**
* 監控倉位
*/
private async monitorPosition(marketData: MarketData): Promise<void> {
if (this.position.gt(0)) {
const pnl = (marketData.price - this.entryPrice) / this.entryPrice;
console.log(`\n📈 Position PnL: ${(pnl * 100).toFixed(2)}%`);
// 止損檢查
if (pnl < -0.05) {
console.log(' ⚠️ Stop loss triggered!');
// 執行止損
await this.executeSell({
action: 'SELL',
confidence: 100,
price: marketData.price,
size: this.position,
reason: 'Stop loss'
});
}
// 止盈檢查
if (pnl > 0.10) {
console.log(' 🎯 Take profit triggered!');
// 執行止盈
await this.executeSell({
action: 'SELL',
confidence: 100,
price: marketData.price,
size: this.position,
reason: 'Take profit'
});
}
}
}
/**
* 工具函數:睡眠
*/
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
// 使用範例
async function main() {
const config: TradingConfig = {
rpcUrl: process.env.RPC_URL || 'https://eth-mainnet.alchemyapi.io/v2/YOUR_API_KEY',
privateKey: process.env.PRIVATE_KEY || '',
maxSlippage: 300, // 3%
minTradeAmount: ethers.utils.parseEther('0.1'),
maxTradeAmount: ethers.utils.parseEther('10'),
pollingInterval: 60000 // 1 分鐘
};
const bot = new AITradingBot(config);
// 優雅退出處理
process.on('SIGINT', () => {
bot.stop();
process.exit(0);
});
await bot.start();
}
main().catch(console.error);
2.2 策略信號產生器
機器學習策略實現:
// strategy/signal-generator.ts - 信號產生器
import { TensorFlow } from '@tensorflow/tfjs-node';
import { RSI, MACD, BollingerBands } from 'technicalindicators';
/**
* 機器學習信號產生器
*/
class MLSignalGenerator {
private model: TensorFlow.LayersModel | null = null;
private lookbackPeriod: number = 60;
private features: string[] = ['rsi', 'macd', 'bb', 'volume', 'price'];
/**
* 加載預訓練模型
*/
async loadModel(modelPath: string): Promise<void> {
this.model = await TensorFlow.loadLayersModel(`file://${modelPath}`);
console.log('✅ ML Model loaded');
}
/**
* 生成交易信號
*/
async generateSignal(prices: number[], volumes: number[]): Promise<{
signal: number; // -1: Sell, 0: Hold, 1: Buy
confidence: number;
}> {
// 計算技術指標
const features = this.extractFeatures(prices, volumes);
// 標準化特徵
const normalizedFeatures = this.normalizeFeatures(features);
// 轉換為模型輸入格式
const input = TensorFlow.tensor2d([normalizedFeatures]);
// 進行預測
const prediction = this.model!.predict(input) as TensorFlow.Tensor;
const probabilities = await prediction.data();
// 解析預測結果
const buyProb = probabilities[0];
const sellProb = probabilities[1];
const holdProb = probabilities[2];
// 確定信號
let signal = 0;
let confidence = holdProb;
if (buyProb > sellProb && buyProb > holdProb) {
signal = 1;
confidence = buyProb;
} else if (sellProb > buyProb && sellProb > holdProb) {
signal = -1;
confidence = sellProb;
}
// 清理內存
input.dispose();
prediction.dispose();
return { signal, confidence };
}
/**
* 提取特徵
*/
private extractFeatures(prices: number[], volumes: number[]): number[] {
// RSI
const rsiValues = RSI.calculate({ values: prices, period: 14 });
const rsi = rsiValues[rsiValues.length - 1] / 100;
// MACD
const macdValues = MACD.calculate({
values: prices,
fastPeriod: 12,
slowPeriod: 26,
signalPeriod: 9,
SimpleMAOscillator: false,
SimpleMASignal: false
});
const macd = macdValues[macdValues.length - 1].MACD || 0;
// Bollinger Bands
const bbValues = BollingerBands.calculate({
values: prices,
period: 20,
stdDev: 2
});
const bb = bbValues[bbValues.length - 1];
const bbPosition = (prices[prices.length - 1] - bb.lower) / (bb.upper - bb.lower);
// 成交量變化
const volumeChange = (volumes[volumes.length - 1] - volumes[volumes.length - 2])
/ volumes[volumes.length - 2];
// 價格動量
const momentum = (prices[prices.length - 1] - prices[prices.length - 10])
/ prices[prices.length - 10];
return [rsi, macd / 1000, bbPosition, volumeChange, momentum];
}
/**
* 標準化特徵
*/
private normalizeFeatures(features: number[]): number[] {
// 簡單的 min-max 標準化
const minMax = [
[0, 1], // RSI
[-1, 1], // MACD
[0, 1], // BB Position
[-1, 1], // Volume Change
[-0.5, 0.5] // Momentum
];
return features.map((value, index) => {
const [min, max] = minMax[index];
return (value - min) / (max - min);
});
}
}
/**
* 組合策略管理器
*/
class StrategyManager {
private strategies: Map<string, Function> = new Map();
constructor() {
// 註冊內置策略
this.strategies.set('ma_cross', this.maCrossStrategy.bind(this));
this.strategies.set('rsi', this.rsiStrategy.bind(this));
this.strategies.set('ml', this.mlStrategy.bind(this));
}
/**
* 移動平均交叉策略
*/
private maCrossStrategy(prices: number[]): { signal: number; confidence: number } {
const maShort = this.calculateSMA(prices, 10);
const maLong = this.calculateSMA(prices, 50);
if (maShort > maLong * 1.02) return { signal: 1, confidence: 80 };
if (maShort < maLong * 0.98) return { signal: -1, confidence: 80 };
return { signal: 0, confidence: 50 };
}
/**
* RSI 策略
*/
private rsiStrategy(prices: number[]): { signal: number; confidence: number } {
const rsi = RSI.calculate({ values: prices, period: 14 });
const currentRSI = rsi[rsi.length - 1];
if (currentRSI < 30) return { signal: 1, confidence: 70 };
if (currentRSI > 70) return { signal: -1, confidence: 70 };
return { signal: 0, confidence: 50 };
}
/**
* ML 策略
*/
private async mlStrategy(prices: number[]): Promise<{ signal: number; confidence: number }> {
// ML 策略需要 volumes 數據
const volumes = new Array(prices.length).fill(1000000);
const mlGenerator = new MLSignalGenerator();
// 這裡應該加載實際模型
// await mlGenerator.loadModel('./models/trading_model.h5');
// 返回預設值
return { signal: 0, confidence: 50 };
}
/**
* 計算 SMA
*/
private calculateSMA(prices: number[], period: number): number {
const slice = prices.slice(-period);
return slice.reduce((a, b) => a + b, 0) / period;
}
/**
* 執行策略
*/
async execute(strategyName: string, prices: number[], volumes?: number[]): Promise<{
signal: number;
confidence: number;
}> {
const strategy = this.strategies.get(strategyName);
if (!strategy) {
throw new Error(`Strategy ${strategyName} not found`);
}
return await strategy(prices, volumes);
}
}
export { AITradingBot, MLSignalGenerator, StrategyManager };
2.3 訂單執行器
高頻交易執行器:
// executor/order-executor.ts - 訂單執行器
import { ethers, BigNumber, Wallet, providers } from 'ethers';
interface Order {
id: string;
type: 'BUY' | 'SELL';
tokenIn: string;
tokenOut: string;
amountIn: BigNumber;
minAmountOut: BigNumber;
deadline: number;
gasLimit: number;
}
interface ExecutionResult {
success: boolean;
transactionHash?: string;
actualAmountOut?: BigNumber;
gasUsed?: BigNumber;
error?: string;
}
/**
* 訂單執行器
*/
class OrderExecutor {
private wallet: Wallet;
private provider: providers.JsonRpcProvider;
private gasPriceStrategy: 'fast' | 'standard' | 'economy';
private maxGasPrice: BigNumber;
constructor(
privateKey: string,
rpcUrl: string,
gasStrategy: 'fast' | 'standard' | 'economy' = 'fast',
maxGasPriceGwei: number = 100
) {
this.provider = new providers.JsonRpcProvider(rpcUrl);
this.wallet = new Wallet(privateKey, this.provider);
this.gasPriceStrategy = gasStrategy;
this.maxGasPrice = ethers.utils.parseUnits(maxGasPriceGwei.toString(), 'gwei');
}
/**
* 執行市價單
*/
async executeMarketOrder(order: Order): Promise<ExecutionResult> {
try {
// 估算 Gas 價格
const gasPrice = await this.estimateGasPrice();
// 估算交易費用
const feeData = await this.provider.getFeeData();
const maxFeePerGas = feeData.maxFeePerGas || gasPrice;
const maxPriorityFeePerGas = feeData.maxPriorityFeePerGas || gasPrice.div(2);
// 構建交易
const tx = {
to: order.tokenIn === ethers.constants.AddressZero ? order.tokenOut : this.getRouterAddress(),
value: order.tokenIn === ethers.constants.AddressZero ? order.amountIn : BigNumber.from(0),
gasLimit: order.gasLimit || 200000,
maxFeePerGas: maxFeePerGas,
maxPriorityFeePerGas: maxPriorityFeePerGas
};
// 發送交易
console.log(`📤 Sending transaction...`);
const response = await this.wallet.sendTransaction(tx);
console.log(`⏳ Waiting for confirmation...`);
const receipt = await response.wait();
if (receipt.status === 1) {
console.log(`✅ Transaction confirmed! Hash: ${receipt.transactionHash}`);
return {
success: true,
transactionHash: receipt.transactionHash,
gasUsed: receipt.gasUsed
};
} else {
return {
success: false,
transactionHash: receipt.transactionHash,
error: 'Transaction reverted'
};
}
} catch (error: any) {
console.error(`❌ Execution failed:`, error.message);
return {
success: false,
error: error.message
};
}
}
/**
* 執行閃電貸套利
*/
async executeFlashSwap(
borrower: string,
tokenIn: string,
amountIn: BigNumber,
path: string[]
): Promise<ExecutionResult> {
const flashLoanExecutor = new ethers.Contract(
this.getFlashLoanExecutorAddress(),
[
'function execute((address token, uint256 amount, bytes data)) external'
],
this.wallet
);
const data = ethers.utils.defaultAbiCoder.encode(
['address[]', 'address'],
[path, this.wallet.address]
);
try {
const gasPrice = await this.estimateGasPrice();
const tx = await flashLoanExecutor.execute(
[tokenIn, amountIn, data],
{
gasLimit: 500000,
gasPrice
}
);
const receipt = await tx.wait();
return {
success: receipt.status === 1,
transactionHash: receipt.transactionHash,
gasUsed: receipt.gasUsed
};
} catch (error: any) {
return {
success: false,
error: error.message
};
}
}
/**
* 批量執行訂單
*/
async batchExecute(orders: Order[]): Promise<ExecutionResult[]> {
const results: ExecutionResult[] = [];
for (const order of orders) {
const result = await this.executeMarketOrder(order);
results.push(result);
// 避免觸發速率限制
await this.sleep(1000);
}
return results;
}
/**
* 估算 Gas 價格
*/
private async estimateGasPrice(): Promise<BigNumber> {
const feeData = await this.provider.getFeeData();
let baseGasPrice = feeData.gasPrice || await this.provider.getGasPrice();
// 根據策略調整
let multiplier = 1;
switch (this.gasPriceStrategy) {
case 'fast':
multiplier = 1.2;
break;
case 'standard':
multiplier = 1.0;
break;
case 'economy':
multiplier = 0.8;
break;
}
let adjustedPrice = baseGasPrice.mul(Math.floor(multiplier * 100)).div(100);
// 檢查是否超過最大限制
if (adjustedPrice.gt(this.maxGasPrice)) {
adjustedPrice = this.maxGasPrice;
}
return adjustedPrice;
}
/**
* 獲取路由器地址(簡化)
*/
private getRouterAddress(): string {
return '0xE592427A0AEce92De3Edee1F18E0157C05861564'; // Uniswap V3
}
/**
* 獲取閃電貸執行器地址
*/
private getFlashLoanExecutorAddress(): string {
return '0x...'; // 部署的執行器地址
}
/**
* 睡眠函數
*/
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
export { OrderExecutor, Order, ExecutionResult };
第三章:風險管理與監控
3.1 實時監控儀表板
監控系統實現:
// monitor/dashboard.ts - 監控儀表板
import { ethers } from 'ethers';
import { DiscordWebhook, TelegramBot } from './notification';
interface BotMetrics {
totalTrades: number;
profitableTrades: number;
totalVolume: BigNumber;
totalProfitLoss: BigNumber;
averageExecutionTime: number;
lastTradeTime: number;
}
interface Position {
token: string;
size: BigNumber;
entryPrice: number;
currentPrice: number;
pnl: number;
timestamp: number;
}
/**
* 交易監控系統
*/
class TradingMonitor {
private provider: ethers.providers.JsonRpcProvider;
private metrics: BotMetrics;
private positions: Map<string, Position> = new Map();
private alerts: AlertConfig[] = [];
private discord?: DiscordWebhook;
private telegram?: TelegramBot;
constructor(
rpcUrl: string,
alertConfig?: { discord?: string; telegram?: string }
) {
this.provider = new ethers.providers.JsonRpcProvider(rpcUrl);
this.metrics = {
totalTrades: 0,
profitableTrades: 0,
totalVolume: ethers.constants.Zero,
totalProfitLoss: ethers.constants.Zero,
averageExecutionTime: 0,
lastTradeTime: 0
};
// 初始化通知渠道
if (alertConfig?.discord) {
this.discord = new DiscordWebhook(alertConfig.discord);
}
if (alertConfig?.telegram) {
this.telegram = new TelegramBot(alertConfig.telegram);
}
}
/**
* 記錄交易
*/
recordTrade(
token: string,
side: 'BUY' | 'SELL',
size: BigNumber,
price: number,
executionTime: number
): void {
this.metrics.totalTrades++;
this.metrics.totalVolume = this.metrics.totalVolume.add(size);
this.metrics.averageExecutionTime =
(this.metrics.averageExecutionTime * (this.metrics.totalTrades - 1) + executionTime)
/ this.metrics.totalTrades;
this.metrics.lastTradeTime = Date.now();
// 更新倉位
if (side === 'BUY') {
this.positions.set(token, {
token,
size,
entryPrice: price,
currentPrice: price,
pnl: 0,
timestamp: Date.now()
});
} else {
const position = this.positions.get(token);
if (position) {
const pnl = (price - position.entryPrice) / position.entryPrice;
this.metrics.totalProfitLoss = this.metrics.totalProfitLoss.add(
position.size.mul(ethers.utils.parseUnits(pnl.toString(), 18))
);
if (pnl > 0) this.metrics.profitableTrades++;
this.positions.delete(token);
this.sendNotification(`Position closed: ${side} ${ethers.utils.formatEther(size)} ${token} @ ${price}, PnL: ${pnl * 100}%`);
}
}
}
/**
* 更新持倉價格
*/
async updatePositions(): Promise<void> {
for (const [token, position] of this.positions) {
const currentPrice = await this.getPrice(token);
position.currentPrice = currentPrice;
position.pnl = (currentPrice - position.entryPrice) / position.entryPrice;
}
}
/**
* 檢查風險閾值
*/
checkRiskThresholds(): void {
// 檢查總虧損
const totalLoss = this.metrics.totalProfitLoss.lt(ethers.constants.Zero);
if (totalLoss) {
const lossAmount = Math.abs(parseFloat(ethers.utils.formatEther(this.metrics.totalProfitLoss)));
if (lossAmount > 10) { // 超過 10 ETH
this.sendAlert('HIGH_LOSS', `Total loss exceeds 10 ETH: ${lossAmount}`);
}
}
// 檢查持倉風險
for (const [token, position] of this.positions) {
if (position.pnl < -0.1) { // 虧損超過 10%
this.sendAlert('STOP_LOSS', `Stop loss triggered for ${token}: ${position.pnl * 100}%`);
}
}
// 檢查交易頻率
const timeSinceLastTrade = Date.now() - this.metrics.lastTradeTime;
if (timeSinceLastTrade > 3600000) { // 超過 1 小時
this.sendAlert('INACTIVE', 'No trades in the last hour');
}
}
/**
* 獲取儀表板數據
*/
getDashboardData(): {
metrics: BotMetrics;
positions: Position[];
health: string;
} {
return {
metrics: this.metrics,
positions: Array.from(this.positions.values()),
health: this.calculateHealth()
};
}
/**
* 計算健康度
*/
private calculateHealth(): string {
if (this.metrics.totalTrades === 0) return 'NEW';
const winRate = this.metrics.profitableTrades / this.metrics.totalTrades;
if (winRate > 0.6) return 'HEALTHY';
if (winRate > 0.4) return 'NEUTRAL';
if (winRate > 0.2) return 'WARNING';
return 'CRITICAL';
}
/**
* 發送通知
*/
private async sendNotification(message: string): Promise<void> {
console.log(`📢 Notification: ${message}`);
if (this.discord) {
await this.discord.send(message);
}
if (this.telegram) {
await this.telegram.send(message);
}
}
/**
* 發送告警
*/
private async sendAlert(type: string, message: string): Promise<void> {
const alertMessage = `🚨 ALERT [${type}]: ${message}`;
console.error(alertMessage);
if (this.discord) {
await this.discord.send(alertMessage);
}
if (this.telegram) {
await this.telegram.send(alertMessage);
}
}
/**
* 獲取代幣價格(簡化)
*/
private async getPrice(token: string): Promise<number> {
// 實際應從價格預言機獲取
return 2000;
}
}
interface AlertConfig {
type: string;
threshold: number;
message: string;
}
export { TradingMonitor, BotMetrics, Position };
結論
本文詳細介紹了 AI 交易代理在以太坊上的完整開發實踐,從系統架構設計、智慧合約開發、到 TypeScript 交易機器人實現,提供了一套完整的解決方案。通過風險管理模組和監控系統的整合,構建了一個可實際運行的自動化交易系統。
關鍵要點回顧:
- 系統架構設計需要考慮可擴展性和容錯性
- 智慧合約實現風險控制邏輯,確保資金安全
- 交易機器人需要整合市場數據、分析引擎和執行模組
- 持續監控和告警是運維的關鍵
後續優化方向:
- 部署機器學習模型進行更精準的價格預測
- 實現多策略組合以分散風險
- 整合更多數據源(社交媒體、新聞等)進行情感分析
- 優化 Gas 費用策略以降低交易成本
- 實現分布式部署以提高系統可用性
風險提示:
加密貨幣交易存在極高風險,AI 交易代理並不保證盈利。在實際部署前,請務必在測試網充分測試,並根據自身風險承受能力設定合理的止損和倉位管理規則。
相關文章
- ERC-4626 Tokenized Vault 完整實現指南:從標準規範到生產級合約 — 本文深入探討 ERC-4626 標準的技術細節,提供完整的生產級合約實現。內容涵蓋標準接口定義、資產與份額轉換的數學模型、收益策略整合、費用機制設計,並提供可直接部署的 Solidity 代碼範例。通過本指南,開發者可以構建安全可靠的代幣化 vault 系統。
- 以太坊智能合約開發實戰:從基礎到 DeFi 協議完整代碼範例指南 — 本文提供以太坊智能合約開發的完整實戰指南,透過可直接運行的 Solidity 代碼範例,幫助開發者從理論走向實踐。內容涵蓋基礎合約開發、借貸協議實作、AMM 機制實現、以及中文圈特有的應用場景(台灣交易所整合、香港監管合規、Singapore MAS 牌照申請)。本指南假設讀者具備基本的程式設計基礎,熟悉 JavaScript 或 Python 等語言,並對區塊鏈概念有基本理解。
- EigenLayer 再質押風險模擬與量化分析:從理論到實踐的完整框架 — 本文深入探討 EigenLayer 再質押協議的風險評估框架與量化分析方法。我們提供完整的質押收益率計算模型、風險調整後收益評估、Monte Carlo 模擬框架,以及 Solidity 智能合約風險示例代碼。通過實際可運行的 Python 程式碼和詳細的風險指標解讀,幫助投資者和開發者系統性地評估和管理再質押風險,做出更明智的質押決策。
- 以太坊穩定幣生態深度技術分析:USDC、USDT、DAI 實際應用案例與風險評估 — 本文深入分析以太坊生態系統中三大主流穩定幣(USDC、USDT、DAI)的技術架構、發行機制、風險模型、實際應用場景以及風險管理策略。從工程師視角剖析 USDC 的合規導向設計、USDT 的市值領導地位與透明度爭議、DAI 的去中心化超額抵押模型,並提供完整的程式碼示例和 2026 年第一季度市場數據,幫助開發者、投資者和機構用戶做出明智的技術決策。
- MEV Sandwich Attack 實務案例深度分析:攻擊機制、檢測方法與防禦策略完整指南 — 三明治攻擊(Sandwich Attack)是 MEV 生態系統中對普通用戶影響最大的攻擊類型。當用戶在去中心化交易所進行交易時,其交易可能被攻擊者「夾擊」——在用戶交易之前搶先執行一筆交易,在用戶交易之後立即執行另一筆交易,從而套取用戶的交易價值。本文深入分析三明治攻擊的技術機制、提供真實攻擊案例、詳述檢測方法,並系統性地探討各種防禦策略。
延伸閱讀與來源
- Ethereum.org Developers 官方開發者入口與技術文件
- EIPs 以太坊改進提案
這篇文章對您有幫助嗎?
請告訴我們如何改進:
評論
發表評論
注意:由於這是靜態網站,您的評論將儲存在本地瀏覽器中,不會公開顯示。
目前尚無評論,成為第一個發表評論的人吧!