跳至主要内容

AI 交易 Hooks

ONE SDK 导出 6 个专用 hooks 用于 AI 驱动的交易,外加 token 管理函数 用于认证。这些 hooks 是 独立的——不需要 OneProvider,并自行管理认证 token。

导入

import {
// Hooks
useAIStrategies,
useAIStrategy,
useAIOrders,
useAIPortfolio,
useAIMarketData,
useAITrading,
// Token management
setAITradingAccessToken,
clearAITradingAccessToken,
} from '@one_deploy/sdk';

Token 管理

需要独立认证

AI 交易 hooks 不会OneProvider 上下文读取数据。你必须在使用任何 AI 交易 hook 之前调用 setAITradingAccessToken。未设置 token 就调用 hook 会产生 UNAUTHORIZED 错误。

设置

import {
setAITradingAccessToken,
clearAITradingAccessToken,
} from '@one_deploy/sdk';

// After your user authenticates (e.g. via your auth flow or OneEngineClient.login)
function onUserLogin(accessToken: string) {
setAITradingAccessToken(accessToken);
}

// On logout, clear the token
function onUserLogout() {
clearAITradingAccessToken();
}

函数签名

/** Set the bearer token used by all AI trading hooks and API calls.
* Call this once after authentication. The token is stored in module-level
* state and shared across all AI trading hook instances. */
function setAITradingAccessToken(token: string): void;

/** Clear the current AI trading access token.
* Subsequent hook calls will return UNAUTHORIZED errors until a new token is set. */
function clearAITradingAccessToken(): void;

完整设置示例

import {
setAITradingAccessToken,
clearAITradingAccessToken,
useAIStrategies,
useAIPortfolio,
} from '@one_deploy/sdk';
import { useEffect, useState } from 'react';

function AITradingApp() {
const [isReady, setIsReady] = useState(false);

useEffect(() => {
// Obtain a token from your auth system
async function init() {
const token = await fetchAccessTokenFromYourAuthService();
setAITradingAccessToken(token);
setIsReady(true);
}
init();

return () => {
clearAITradingAccessToken();
};
}, []);

if (!isReady) return <p>Authenticating...</p>;

return (
<>
<StrategyList />
<PortfolioSummary />
</>
);
}

useAIStrategies

获取和筛选可用的 AI 交易策略。

签名

function useAIStrategies(options?: UseAIStrategiesOptions): UseAIStrategiesResult;

选项

interface UseAIStrategiesOptions {
/** Filter by strategy category. */
category?: StrategyCategory;

/** Filter by risk level. */
riskLevel?: RiskLevel;

/** Filter by supported chain ID. */
chainId?: number;

/** Filter by trading pair (e.g. 'ETH/USDT'). */
pair?: string;

/** Enable automatic polling. Defaults to false. */
autoRefresh?: boolean;

/** Polling interval in milliseconds. Defaults to 60000. */
refreshInterval?: number;
}

type StrategyCategory =
| 'conservative'
| 'balanced'
| 'aggressive'
| 'hedge'
| 'arbitrage'
| 'trend'
| 'grid'
| 'dca';

type RiskLevel = 'conservative' | 'moderate' | 'aggressive';

返回类型

interface UseAIStrategiesResult {
/** Array of strategies matching the filter criteria. */
strategies: AIStrategy[];

/** Whether the initial fetch is in progress. */
isLoading: boolean;

/** Error object, or null. */
error: OneSDKError | null;

/** Manually trigger a refetch. */
refetch: () => Promise<void>;
}

interface AIStrategy {
id: string;
name: string;
description: string;
category: StrategyCategory;
riskLevel: RiskLevel;
supportedChains: number[];
supportedPairs: string[];
minInvestment: number;
maxInvestment: number;
expectedApy: { min: number; max: number };
lockPeriodDays: number;
isActive: boolean;
createdAt: string;
}

用法

import { useAIStrategies } from '@one_deploy/sdk';

function StrategyList() {
const { strategies, isLoading, error } = useAIStrategies({
category: 'balanced',
riskLevel: 'moderate',
});

if (isLoading) return <p>Loading strategies...</p>;
if (error) return <p>Error: {error.message}</p>;

return (
<ul>
{strategies.map((s) => (
<li key={s.id}>
<strong>{s.name}</strong> -- {s.description}
<br />
APY: {s.expectedApy.min}% - {s.expectedApy.max}% | Lock: {s.lockPeriodDays} days
<br />
Min: ${s.minInvestment} | Risk: {s.riskLevel}
</li>
))}
</ul>
);
}

useAIStrategy

按 ID 获取单个 AI 策略。适用于详情页。

签名

function useAIStrategy(strategyId?: string): UseAIStrategyResult;

参数

参数类型必需描述
strategyIdstring要获取的策略 ID。当为 undefined 时,hook 处于空闲状态(不发起请求)。

返回类型

interface UseAIStrategyResult {
/** The strategy object, or null if not yet loaded. */
strategy: AIStrategy | null;

/** Whether the fetch is in progress. */
isLoading: boolean;

/** Error object, or null. */
error: OneSDKError | null;

/** Manually trigger a refetch. */
refetch: () => Promise<void>;
}

用法

import { useAIStrategy } from '@one_deploy/sdk';

function StrategyDetail({ strategyId }: { strategyId: string }) {
const { strategy, isLoading, error } = useAIStrategy(strategyId);

if (isLoading) return <p>Loading strategy...</p>;
if (error) return <p>Error: {error.message}</p>;
if (!strategy) return <p>Strategy not found.</p>;

return (
<div>
<h2>{strategy.name}</h2>
<p>{strategy.description}</p>
<dl>
<dt>Category</dt><dd>{strategy.category}</dd>
<dt>Risk Level</dt><dd>{strategy.riskLevel}</dd>
<dt>Expected APY</dt><dd>{strategy.expectedApy.min}% - {strategy.expectedApy.max}%</dd>
<dt>Lock Period</dt><dd>{strategy.lockPeriodDays} days</dd>
<dt>Investment Range</dt><dd>${strategy.minInvestment} - ${strategy.maxInvestment}</dd>
<dt>Supported Chains</dt><dd>{strategy.supportedChains.join(', ')}</dd>
<dt>Supported Pairs</dt><dd>{strategy.supportedPairs.join(', ')}</dd>
</dl>
</div>
);
}

useAIOrders

查询已认证用户的当前和历史 AI 交易订单。

签名

function useAIOrders(options?: UseAIOrdersOptions): UseAIOrdersResult;

选项

interface UseAIOrdersOptions {
/** Filter by order status. */
status?: AIOrderStatus;

/** Filter by strategy ID. */
strategyId?: string;

/** Filter by chain ID. */
chainId?: number;

/** Maximum number of orders to return. Defaults to 50. */
limit?: number;

/** Pagination offset. Defaults to 0. */
offset?: number;

/** Enable automatic polling. Defaults to false. */
autoRefresh?: boolean;

/** Polling interval in milliseconds. Defaults to 30000. */
refreshInterval?: number;
}

type AIOrderStatus =
| 'active'
| 'paused'
| 'completed'
| 'cancelled'
| 'redeeming'
| 'redeemed';

返回类型

interface UseAIOrdersResult {
/** Array of orders matching the filter criteria. */
orders: AIOrder[];

/** Total number of matching orders (for pagination). */
total: number;

/** Whether the initial fetch is in progress. */
isLoading: boolean;

/** Error object, or null. */
error: OneSDKError | null;

/** Manually trigger a refetch. */
refetch: () => Promise<void>;
}

interface AIOrder {
id: string;
strategyId: string;
strategyName: string;
status: AIOrderStatus;
chainId: number;
pair: string;
investedAmount: number;
currentValue: number;
pnl: number;
pnlPercentage: number;
startedAt: string;
expiresAt: string;
lastTradeAt: string | null;
}

用法

import { useAIOrders } from '@one_deploy/sdk';

function ActiveOrders() {
const { orders, total, isLoading, error } = useAIOrders({
status: 'active',
autoRefresh: true,
refreshInterval: 15000,
});

if (isLoading) return <p>Loading orders...</p>;
if (error) return <p>Error: {error.message}</p>;

return (
<div>
<h2>Active Orders ({total})</h2>
{orders.map((order) => (
<div key={order.id} style={{ padding: 12, borderBottom: '1px solid #eee' }}>
<strong>{order.strategyName}</strong> -- {order.pair}
<br />
Invested: ${order.investedAmount.toFixed(2)} |
Current: ${order.currentValue.toFixed(2)} |
P&L: <span style={{ color: order.pnl >= 0 ? 'green' : 'red' }}>
{order.pnl >= 0 ? '+' : ''}{order.pnlPercentage.toFixed(2)}%
</span>
</div>
))}
</div>
);
}

useAIPortfolio

返回所有 AI 交易头寸的汇总投资组合指标和盈亏数据。

签名

function useAIPortfolio(): UseAIPortfolioResult;

返回类型

interface UseAIPortfolioResult {
/** Portfolio summary object, or null if not loaded. */
portfolio: AIPortfolioSummary | null;

/** Whether the fetch is in progress. */
isLoading: boolean;

/** Error object, or null. */
error: OneSDKError | null;

/** Manually trigger a refetch. */
refetch: () => Promise<void>;
}

interface AIPortfolioSummary {
totalInvested: number;
totalCurrentValue: number;
totalPnl: number;
totalPnlPercentage: number;
activeOrderCount: number;
completedOrderCount: number;
bestPerformingStrategy: string | null;
worstPerformingStrategy: string | null;
lastUpdated: string;
}

用法

import { useAIPortfolio } from '@one_deploy/sdk';

function PortfolioSummary() {
const { portfolio, isLoading, error } = useAIPortfolio();

if (isLoading) return <p>Loading portfolio...</p>;
if (error) return <p>Error: {error.message}</p>;
if (!portfolio) return <p>No portfolio data.</p>;

return (
<div>
<h2>AI Trading Portfolio</h2>
<dl>
<dt>Total Invested</dt><dd>${portfolio.totalInvested.toFixed(2)}</dd>
<dt>Current Value</dt><dd>${portfolio.totalCurrentValue.toFixed(2)}</dd>
<dt>Total P&L</dt>
<dd style={{ color: portfolio.totalPnl >= 0 ? 'green' : 'red' }}>
{portfolio.totalPnl >= 0 ? '+' : ''}${portfolio.totalPnl.toFixed(2)}
({portfolio.totalPnlPercentage.toFixed(2)}%)
</dd>
<dt>Active Orders</dt><dd>{portfolio.activeOrderCount}</dd>
<dt>Completed Orders</dt><dd>{portfolio.completedOrderCount}</dd>
</dl>
</div>
);
}

useAIMarketData

提供 AI 交易系统支持的交易对的实时市场数据。

签名

function useAIMarketData(): UseAIMarketDataResult;

返回类型

interface UseAIMarketDataResult {
/** Array of market data entries for supported pairs. */
marketData: AIMarketDataEntry[];

/** Whether the fetch is in progress. */
isLoading: boolean;

/** Error object, or null. */
error: OneSDKError | null;

/** Manually trigger a refetch. */
refetch: () => Promise<void>;
}

interface AIMarketDataEntry {
pair: string;
price: number;
change24h: number;
volume24h: number;
high24h: number;
low24h: number;
lastUpdated: string;
}

用法

import { useAIMarketData } from '@one_deploy/sdk';

function MarketOverview() {
const { marketData, isLoading, error } = useAIMarketData();

if (isLoading) return <p>Loading market data...</p>;
if (error) return <p>Error: {error.message}</p>;

return (
<table>
<thead>
<tr>
<th>交易对</th>
<th>价格</th>
<th>24h 涨跌</th>
<th>24h 最高</th>
<th>24h 最低</th>
<th>成交量</th>
</tr>
</thead>
<tbody>
{marketData.map((d) => (
<tr key={d.pair}>
<td>{d.pair}</td>
<td>${d.price.toLocaleString()}</td>
<td style={{ color: d.change24h >= 0 ? 'green' : 'red' }}>
{d.change24h >= 0 ? '+' : ''}{d.change24h.toFixed(2)}%
</td>
<td>${d.high24h.toLocaleString()}</td>
<td>${d.low24h.toLocaleString()}</td>
<td>${(d.volume24h / 1e6).toFixed(1)}M</td>
</tr>
))}
</tbody>
</table>
);
}

useAITrading

一个 组合 hook,将上述五个 hooks 的功能聚合到一个接口中。当你需要同时使用策略、订单、投资组合和市场数据而不想分别导入每个 hook 时,使用此 hook。

签名

function useAITrading(): UseAITradingResult;

返回类型

interface UseAITradingResult {
/** Available strategies. */
strategies: AIStrategy[];

/** User's orders. */
orders: AIOrder[];

/** Portfolio summary. */
portfolio: AIPortfolioSummary | null;

/** Market data for supported pairs. */
marketData: AIMarketDataEntry[];

/** Create a new AI trading order. */
createOrder: (params: CreateAIOrderParams) => Promise<AIOrder>;

/** Pause an active order. */
pauseOrder: (orderId: string) => Promise<void>;

/** Resume a paused order. */
resumeOrder: (orderId: string) => Promise<void>;

/** Redeem (withdraw from) a completed or active order. */
redeemOrder: (orderId: string) => Promise<void>;

/** Whether any data is loading. */
isLoading: boolean;

/** The most recent error, or null. */
error: OneSDKError | null;

/** Refetch all data. */
refetch: () => Promise<void>;
}

interface CreateAIOrderParams {
strategyId: string;
chainId: number;
pair: string;
amount: number;
/** Optional: override the default risk level from the strategy. */
riskLevel?: RiskLevel;
}

用法

import { useAITrading } from '@one_deploy/sdk';

function TradingDashboard() {
const {
strategies,
orders,
portfolio,
marketData,
createOrder,
pauseOrder,
redeemOrder,
isLoading,
error,
refetch,
} = useAITrading();

if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;

const handleCreateOrder = async () => {
const order = await createOrder({
strategyId: strategies[0].id,
chainId: 8453,
pair: 'ETH/USDT',
amount: 500,
});
console.log('Created order:', order.id);
await refetch();
};

return (
<div>
{/* Portfolio summary */}
{portfolio && (
<div>
<h2>Portfolio: ${portfolio.totalCurrentValue.toFixed(2)}</h2>
<p>
P&L: {portfolio.totalPnl >= 0 ? '+' : ''}${portfolio.totalPnl.toFixed(2)}
({portfolio.totalPnlPercentage.toFixed(2)}%)
</p>
</div>
)}

{/* Active orders */}
<h3>Active Orders ({orders.filter((o) => o.status === 'active').length})</h3>
{orders
.filter((o) => o.status === 'active')
.map((order) => (
<div key={order.id}>
<span>{order.strategyName} -- {order.pair}</span>
<button onClick={() => pauseOrder(order.id)}>Pause</button>
<button onClick={() => redeemOrder(order.id)}>Redeem</button>
</div>
))}

{/* Create new order */}
<button onClick={handleCreateOrder}>Create Order</button>

{/* Market data */}
<h3>Market</h3>
{marketData.map((d) => (
<span key={d.pair} style={{ marginRight: 16 }}>
{d.pair}: ${d.price.toLocaleString()}
</span>
))}
</div>
);
}

完整集成示例

端到端示例展示 token 设置、策略选择、订单创建和投资组合展示:

import {
setAITradingAccessToken,
clearAITradingAccessToken,
useAIStrategies,
useAITrading,
} from '@one_deploy/sdk';
import { useEffect, useState } from 'react';

function AITradingScreen({ userAccessToken }: { userAccessToken: string }) {
const [ready, setReady] = useState(false);

// 1. Set the token on mount
useEffect(() => {
setAITradingAccessToken(userAccessToken);
setReady(true);
return () => clearAITradingAccessToken();
}, [userAccessToken]);

if (!ready) return <p>Initializing AI trading...</p>;

return <TradingContent />;
}

function TradingContent() {
const { strategies, isLoading: strategiesLoading } = useAIStrategies({
category: 'balanced',
});

const {
orders,
portfolio,
createOrder,
redeemOrder,
isLoading: tradingLoading,
error,
} = useAITrading();

const [selectedStrategy, setSelectedStrategy] = useState<string | null>(null);

if (strategiesLoading || tradingLoading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;

const handleInvest = async () => {
if (!selectedStrategy) return;

const order = await createOrder({
strategyId: selectedStrategy,
chainId: 8453,
pair: 'ETH/USDT',
amount: 1000,
});
console.log('New order:', order.id);
};

return (
<div>
{/* Strategy picker */}
<h2>Select a Strategy</h2>
<select
value={selectedStrategy ?? ''}
onChange={(e) => setSelectedStrategy(e.target.value || null)}
>
<option value="">-- Choose --</option>
{strategies.map((s) => (
<option key={s.id} value={s.id}>
{s.name} (APY: {s.expectedApy.min}-{s.expectedApy.max}%)
</option>
))}
</select>
<button onClick={handleInvest} disabled={!selectedStrategy}>
Invest $1,000
</button>

{/* Portfolio */}
{portfolio && (
<div>
<h2>Portfolio</h2>
<p>Value: ${portfolio.totalCurrentValue.toFixed(2)}</p>
<p>P&L: {portfolio.totalPnlPercentage.toFixed(2)}%</p>
</div>
)}

{/* Orders */}
<h2>Orders ({orders.length})</h2>
{orders.map((o) => (
<div key={o.id}>
{o.strategyName} | {o.pair} | ${o.currentValue.toFixed(2)} |
{o.status === 'active' && (
<button onClick={() => redeemOrder(o.id)}>Redeem</button>
)}
</div>
))}
</div>
);
}

另请参阅