机器人控制台
机器人控制台提供了对 AI 交易代理活动的实时可见性:包括 NAV(净资产价值)随时间的变化、单笔交易执行记录,以及各持仓的资金分配。使用 botSimulationEngine 服务进行客户端预测,使用 OneEngineClient API 获取实时数据。
botSimulationEngine 服务
botSimulationEngine 是一个客户端模拟引擎,可以预测未来的 NAV 走势,并针对历史数据回测策略。
import { botSimulationEngine } from '@one_deploy/sdk';
运行模拟
import { botSimulationEngine } from '@one_deploy/sdk';
const simulation = await botSimulationEngine.simulate({
strategyId: 'strat_abc123',
pair: 'ETH_USDT',
initialCapital: 1000,
cycleDays: 30,
riskLevel: 'moderate',
});
console.log('Projected final NAV:', simulation.projectedNav);
console.log('Projected return:', simulation.projectedReturn, '%');
console.log('Max drawdown:', simulation.maxDrawdown, '%');
console.log('Snapshots:', simulation.snapshots.length);
// Each snapshot represents one simulated day
simulation.snapshots.forEach((snap) => {
console.log(`Day ${snap.day}: NAV $${snap.nav.toFixed(2)}`);
});
模拟选项
interface BotSimulationOptions {
/** Strategy to simulate. */
strategyId: string;
/** Trading pair. */
pair: string;
/** Starting capital in quote currency. */
initialCapital: number;
/** Number of days to simulate. */
cycleDays: number;
/** Risk level for the simulation. */
riskLevel: RiskLevel;
/** Number of Monte Carlo iterations. Defaults to 1000. */
iterations?: number;
/** Use historical data for back-testing. Defaults to false (forward projection). */
useHistorical?: boolean;
}
interface BotSimulationResult {
projectedNav: number;
projectedReturn: number;
maxDrawdown: number;
sharpeRatio: number;
winRate: number;
totalTrades: number;
snapshots: BotSimulationSnapshot[];
}
interface BotSimulationSnapshot {
day: number;
nav: number;
dailyReturn: number;
cumulativeReturn: number;
drawdown: number;
}
NAV 快照
NAV 快照追踪活跃订单的净资产价值随时间的变化。AINavSnapshot 类型在投资组合、机器人控制台和模拟结果中均有使用。
AINavSnapshot 类型
interface AINavSnapshot {
/** ISO 8601 timestamp of the snapshot. */
timestamp: string;
/** Net asset value at this point in time. */
nav: number;
/** Daily return percentage. */
dailyReturn: number;
/** Cumulative return percentage since order creation. */
cumulativeReturn: number;
/** Current drawdown from peak NAV. */
drawdown: number;
/** Number of open positions at this snapshot. */
openPositions: number;
}
获取订单的 NAV 历史
特定订单的 NAV 快照可通过订单详情端点获取。
import { OneEngineClient } from '@one_deploy/sdk';
const engine = new OneEngineClient({
apiKey: process.env.ONE_API_KEY!,
projectId: process.env.ONE_PROJECT_ID!,
});
// Fetch order with NAV history included
const order = await engine.getAIOrder('order_xyz789', {
includeNavHistory: true,
});
order.navHistory?.forEach((snap) => {
console.log(
`${snap.timestamp}: NAV $${snap.nav.toFixed(2)} ` +
`(${snap.cumulativeReturn >= 0 ? '+' : ''}${snap.cumulativeReturn.toFixed(2)}%)`
);
});
交易历史
getAITradeHistory 方法返回 AI 代理为给定策略或订单执行的交易列表。
getAITradeHistory
const trades = await engine.getAITradeHistory('strat_abc123', 50);
trades.forEach((trade) => {
console.log(
`${trade.action} ${trade.pair} @ ${trade.price} -- ` +
`Size: ${trade.size} -- P&L: ${trade.realisedPnl}`
);
});
方法签名
getAITradeHistory(strategyId: string, limit?: number): Promise<AITradeExecution[]>
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
strategyId | string | 是 | -- | 要查询的策略或订单 ID |
limit | number | 否 | 100 | 返回的最大交易数量 |
AITradeExecution 类型
interface AITradeExecution {
/** Unique trade execution identifier. */
id: string;
/** The order ID this trade belongs to. */
orderId: string;
/** Strategy ID. */
strategyId: string;
/** Trading pair symbol. */
pair: string;
/** Trade action taken. */
action: TradeAction;
/** Execution price. */
price: number;
/** Trade size in base currency. */
size: number;
/** Trade size in quote currency. */
quoteSize: number;
/** Realised profit/loss from this trade (0 for opening trades). */
realisedPnl: number;
/** Fee paid for this trade. */
fee: number;
/** ISO 8601 execution timestamp. */
executedAt: string;
/** On-chain transaction hash, if applicable. */
txHash?: string;
}
交易分配
getAITradeAllocations 方法返回当前各持仓的资金分配情况。
getAITradeAllocations
const allocations = await engine.getAITradeAllocations(20);
allocations.forEach((alloc) => {
console.log(
`${alloc.pair}: ${alloc.direction} -- ` +
`Size: $${alloc.notionalValue.toFixed(2)} -- ` +
`Weight: ${(alloc.weight * 100).toFixed(1)}%`
);
});
方法签名
getAITradeAllocations(limit?: number): Promise<AITradeAllocation[]>
| 参数 | 类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
limit | number | 否 | 50 | 返回的最大分配数量 |
AITradeAllocation 类型
interface AITradeAllocation {
/** Unique allocation identifier. */
id: string;
/** Order ID this allocation belongs to. */
orderId: string;
/** Trading pair symbol. */
pair: string;
/** Position direction. */
direction: 'long' | 'short';
/** Entry price. */
entryPrice: number;
/** Current mark price. */
markPrice: number;
/** Position size in base currency. */
size: number;
/** Notional value in quote currency. */
notionalValue: number;
/** Portfolio weight (0-1). */
weight: number;
/** Unrealised P&L. */
unrealisedPnl: number;
/** Unrealised P&L percentage. */
unrealisedPnlPercent: number;
/** ISO 8601 timestamp when this position was opened. */
openedAt: string;
}
构建控制台视图
以下是一个完整示例,将 NAV 图表、交易历史和分配情况整合到一个控制台页面中。
import { useState, useEffect } from 'react';
import { OneEngineClient, botSimulationEngine } from '@one_deploy/sdk';
import type {
AINavSnapshot,
AITradeExecution,
AITradeAllocation,
} from '@one_deploy/sdk';
interface ConsoleProps {
engine: OneEngineClient;
orderId: string;
strategyId: string;
}
function BotConsole({ engine, orderId, strategyId }: ConsoleProps) {
const [navHistory, setNavHistory] = useState<AINavSnapshot[]>([]);
const [trades, setTrades] = useState<AITradeExecution[]>([]);
const [allocations, setAllocations] = useState<AITradeAllocation[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function loadData() {
setLoading(true);
try {
const [orderDetail, tradeHistory, tradeAllocations] = await Promise.all([
engine.getAIOrder(orderId, { includeNavHistory: true }),
engine.getAITradeHistory(strategyId, 50),
engine.getAITradeAllocations(20),
]);
setNavHistory(orderDetail.navHistory ?? []);
setTrades(tradeHistory);
setAllocations(tradeAllocations);
} finally {
setLoading(false);
}
}
loadData();
}, [orderId, strategyId]);
if (loading) return <ActivityIndicator />;
return (
<ScrollView style={styles.console}>
{/* NAV Chart */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>Net Asset Value</Text>
{navHistory.length > 0 && (
<View>
<Text style={styles.currentNav}>
${navHistory[navHistory.length - 1].nav.toFixed(2)}
</Text>
<Text
style={{
color:
navHistory[navHistory.length - 1].cumulativeReturn >= 0
? '#22c55e'
: '#ef4444',
}}
>
{navHistory[navHistory.length - 1].cumulativeReturn >= 0 ? '+' : ''}
{navHistory[navHistory.length - 1].cumulativeReturn.toFixed(2)}%
</Text>
{/* Render your chart component with navHistory data */}
</View>
)}
</View>
{/* Open Positions */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>Open Positions ({allocations.length})</Text>
{allocations.map((alloc) => (
<View key={alloc.id} style={styles.allocationRow}>
<Text style={styles.pair}>{alloc.pair}</Text>
<Text>{alloc.direction.toUpperCase()}</Text>
<Text>Entry: ${alloc.entryPrice.toFixed(4)}</Text>
<Text>Mark: ${alloc.markPrice.toFixed(4)}</Text>
<Text>Size: ${alloc.notionalValue.toFixed(2)}</Text>
<Text>Weight: {(alloc.weight * 100).toFixed(1)}%</Text>
<Text
style={{
color: alloc.unrealisedPnl >= 0 ? '#22c55e' : '#ef4444',
}}
>
P&L: {alloc.unrealisedPnl >= 0 ? '+' : ''}
${alloc.unrealisedPnl.toFixed(2)} ({alloc.unrealisedPnlPercent.toFixed(2)}%)
</Text>
</View>
))}
</View>
{/* Trade History */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>Recent Trades ({trades.length})</Text>
{trades.map((trade) => (
<View key={trade.id} style={styles.tradeRow}>
<Text style={styles.action}>{trade.action.toUpperCase()}</Text>
<Text>{trade.pair}</Text>
<Text>Price: ${trade.price.toFixed(4)}</Text>
<Text>Size: {trade.size}</Text>
<Text>P&L: ${trade.realisedPnl.toFixed(2)}</Text>
<Text style={styles.timestamp}>
{new Date(trade.executedAt).toLocaleString()}
</Text>
</View>
))}
</View>
</ScrollView>
);
}