Portfolio Dashboard
The portfolio dashboard provides an aggregated view of all AI trading orders, including total invested capital, current NAV, profit/loss, and per-strategy breakdowns. Use the useAIPortfolio hook in React or the getAIPortfolio API method from any platform.
useAIPortfolio Hook
import { useAIPortfolio } from '@one_deploy/sdk';
import type { UseAIPortfolioResult } from '@one_deploy/sdk';
UseAIPortfolioResult
interface UseAIPortfolioResult {
/** Aggregated portfolio summary. Null until the first successful fetch. */
portfolio: AIPortfolioSummary | null;
/** True while the initial fetch is in progress. */
isLoading: boolean;
/** Error object if the fetch failed, otherwise null. */
error: Error | null;
/** Re-fetch portfolio data. */
refetch: () => Promise<void>;
}
Basic Usage
import { useAIPortfolio } from '@one_deploy/sdk';
function PortfolioDashboard() {
const { portfolio, isLoading, error, refetch } = useAIPortfolio();
if (isLoading) return <Text>Loading portfolio...</Text>;
if (error) return <Text>Error: {error.message}</Text>;
if (!portfolio) return <Text>No portfolio data</Text>;
return (
<View style={styles.container}>
<Text style={styles.heading}>AI Trading Portfolio</Text>
<View style={styles.statsRow}>
<StatCard label="Total Invested" value={`$${portfolio.totalInvested.toFixed(2)}`} />
<StatCard label="Current NAV" value={`$${portfolio.currentNav.toFixed(2)}`} />
</View>
<View style={styles.statsRow}>
<StatCard
label="Total P&L"
value={`${portfolio.totalPnl >= 0 ? '+' : ''}$${portfolio.totalPnl.toFixed(2)}`}
/>
<StatCard
label="Return"
value={`${portfolio.totalPnlPercent >= 0 ? '+' : ''}${portfolio.totalPnlPercent.toFixed(2)}%`}
/>
</View>
<View style={styles.statsRow}>
<StatCard label="Active Orders" value={String(portfolio.activeOrders)} />
<StatCard label="Completed" value={String(portfolio.completedOrders)} />
</View>
<Pressable onPress={refetch}>
<Text style={styles.refreshButton}>Refresh</Text>
</Pressable>
</View>
);
}
AIPortfolioSummary Type
interface AIPortfolioSummary {
/** Total capital invested across all orders (in USD). */
totalInvested: number;
/** Current total net asset value across all active orders. */
currentNav: number;
/** Total profit/loss amount (currentNav - totalInvested for active orders + realised P&L). */
totalPnl: number;
/** Total profit/loss as a percentage. */
totalPnlPercent: number;
/** Number of currently active orders. */
activeOrders: number;
/** Number of completed orders (cycle ended). */
completedOrders: number;
/** Number of redeemed orders (early withdrawal). */
redeemedOrders: number;
/** Number of paused orders. */
pausedOrders: number;
/** Per-strategy breakdown. */
strategyBreakdown: AIStrategyBreakdown[];
/** Per-chain breakdown. */
chainBreakdown: AIChainBreakdown[];
/** Historical daily NAV snapshots for portfolio-level charting. */
navHistory: AINavSnapshot[];
}
interface AIStrategyBreakdown {
strategyId: string;
strategyName: string;
category: StrategyCategory;
invested: number;
currentNav: number;
pnl: number;
pnlPercent: number;
orderCount: number;
}
interface AIChainBreakdown {
chainId: number;
chainName: string;
invested: number;
currentNav: number;
pnl: number;
orderCount: number;
}
getAIPortfolio API Method
For non-React environments or when you need direct control, use the engine client.
import { OneEngineClient } from '@one_deploy/sdk';
const engine = new OneEngineClient({
apiKey: process.env.ONE_API_KEY!,
projectId: process.env.ONE_PROJECT_ID!,
});
const portfolio = await engine.getAIPortfolio({
includeNavHistory: true,
includeBreakdowns: true,
});
console.log('Total invested:', portfolio.totalInvested);
console.log('Current NAV:', portfolio.currentNav);
console.log('P&L:', portfolio.totalPnl);
console.log('Active orders:', portfolio.activeOrders);
Method Signature
getAIPortfolio(include?: AIPortfolioInclude): Promise<AIPortfolioSummary>
interface AIPortfolioInclude {
/** Include the navHistory array. Defaults to false. */
includeNavHistory?: boolean;
/** Include strategyBreakdown and chainBreakdown. Defaults to false. */
includeBreakdowns?: boolean;
/** Number of days of NAV history to include. Defaults to 30. */
navHistoryDays?: number;
}
getPortfolioStats API Method
A lighter endpoint that returns only the top-level aggregate numbers, without breakdowns or history. Useful for summary badges or notification counts.
const stats = await engine.getPortfolioStats();
console.log('Active orders:', stats.activeOrders);
console.log('Total P&L:', stats.totalPnl);
console.log('Total invested:', stats.totalInvested);
Method Signature
getPortfolioStats(): Promise<AIPortfolioStats>
interface AIPortfolioStats {
totalInvested: number;
currentNav: number;
totalPnl: number;
totalPnlPercent: number;
activeOrders: number;
completedOrders: number;
redeemedOrders: number;
pausedOrders: number;
}
Building a Dashboard View
Here is a more complete example that combines summary stats, strategy breakdown, and a NAV chart.
import { useAIPortfolio } from '@one_deploy/sdk';
import type { AIStrategyBreakdown, AINavSnapshot } from '@one_deploy/sdk';
function FullDashboard() {
const { portfolio, isLoading, error } = useAIPortfolio();
if (isLoading) return <ActivityIndicator />;
if (error) return <Text>Failed to load portfolio</Text>;
if (!portfolio) return <Text>No data</Text>;
return (
<ScrollView style={styles.container}>
{/* Top-level stats */}
<View style={styles.header}>
<Text style={styles.navValue}>${portfolio.currentNav.toFixed(2)}</Text>
<Text
style={[
styles.pnl,
{ color: portfolio.totalPnl >= 0 ? '#22c55e' : '#ef4444' },
]}
>
{portfolio.totalPnl >= 0 ? '+' : ''}
${portfolio.totalPnl.toFixed(2)} ({portfolio.totalPnlPercent.toFixed(2)}%)
</Text>
</View>
{/* Order counts */}
<View style={styles.countsRow}>
<Badge label="Active" count={portfolio.activeOrders} />
<Badge label="Paused" count={portfolio.pausedOrders} />
<Badge label="Completed" count={portfolio.completedOrders} />
<Badge label="Redeemed" count={portfolio.redeemedOrders} />
</View>
{/* NAV History Chart */}
{portfolio.navHistory.length > 0 && (
<View style={styles.chartContainer}>
<Text style={styles.sectionTitle}>Portfolio Value</Text>
<NavChart data={portfolio.navHistory} />
</View>
)}
{/* Strategy Breakdown */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>By Strategy</Text>
{portfolio.strategyBreakdown.map((sb: AIStrategyBreakdown) => (
<View key={sb.strategyId} style={styles.breakdownRow}>
<Text style={styles.strategyName}>{sb.strategyName}</Text>
<Text style={styles.category}>{sb.category}</Text>
<Text>Invested: ${sb.invested.toFixed(2)}</Text>
<Text>NAV: ${sb.currentNav.toFixed(2)}</Text>
<Text
style={{ color: sb.pnl >= 0 ? '#22c55e' : '#ef4444' }}
>
P&L: {sb.pnl >= 0 ? '+' : ''}${sb.pnl.toFixed(2)} ({sb.pnlPercent.toFixed(2)}%)
</Text>
<Text>Orders: {sb.orderCount}</Text>
</View>
))}
</View>
{/* Chain Breakdown */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>By Chain</Text>
{portfolio.chainBreakdown.map((cb) => (
<View key={cb.chainId} style={styles.breakdownRow}>
<Text>{cb.chainName}</Text>
<Text>Invested: ${cb.invested.toFixed(2)}</Text>
<Text>NAV: ${cb.currentNav.toFixed(2)}</Text>
<Text>Orders: {cb.orderCount}</Text>
</View>
))}
</View>
</ScrollView>
);
}
Next Steps
- Bot Console -- monitor individual order NAV snapshots and trade history.
- Strategy Management -- manage active orders (pause, resume, redeem).
- Early Withdrawal -- understand redemption penalties.