跳至主要内容

提前赎回

用户可以在投资周期结束前赎回 AI 交易订单。赎回时,将根据周期已经过的时间比例收取提前赎回罚金。本页介绍罚金公式、赎回 API 和返回结果的结构。

罚金机制

罚金旨在限制过早提取,同时仍然允许用户在需要时退出。提取越早,罚金越高。

Penalty decreases as cycle progresses:

100% ┐
│ ████
75% │ ████████
│ ████████████
50% │ ████████████████
│ ████████████████████
25% │ ████████████████████████
│ ████████████████████████████
0% └────────────────────────────────
0% 25% 50% 75% 100%
Cycle Completion

罚金公式

罚金按毛利润(而非总资金)的百分比计算。如果订单处于亏损状态,不会对亏损部分收取罚金。

completionRate = daysElapsed / cycleDays

penaltyPercent = maxPenaltyPercent * (1 - completionRate)

penaltyAmount = max(0, grossProfit) * penaltyPercent

netPayout = finalNav - penaltyAmount

其中:

变量描述
completionRate周期已经过的比例(0 到 1)
daysElapsed订单激活以来经过的天数
cycleDays总锁定期天数
maxPenaltyPercent最大罚金百分比,通常为 30%(0.30)
grossProfitfinalNav - investedAmount(可以为负数)
penaltyAmount作为罚金扣除的绝对金额
netPayout返还给用户的金额
亏损不收罚金

如果订单处于亏损状态(grossProfit <= 0),则不收取罚金。无论周期完成率如何,用户都将收到完整的 finalNav。罚金仅适用于利润部分。

罚金示例

下表展示了在 30% 最大罚金下,初始投资 $1,000、毛利润 $200(最终 NAV $1,200)在不同完成率下的罚金情况。

完成率已过天数(30 天周期)罚金 %罚金金额净支付
0%(第 0 天)030%$60.00$1,140.00
25%(第 7.5 天)7.522.5%$45.00$1,155.00
50%(第 15 天)1515%$30.00$1,170.00
75%(第 22.5 天)22.57.5%$15.00$1,185.00
90%(第 27 天)273%$6.00$1,194.00
100%(第 30 天)300%$0.00$1,200.00

如果同一订单处于亏损状态(例如最终 NAV $950,毛利润 -$50):

完成率罚金 %罚金金额净支付
任何0%$0.00$950.00

赎回订单

使用 redeemAIOrder 方法执行提前赎回。此方法适用于 activepaused 状态的订单。

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

setAITradingAccessToken(userToken);

const engine = new OneEngineClient({
apiKey: process.env.ONE_API_KEY!,
projectId: process.env.ONE_PROJECT_ID!,
});

const result = await engine.redeemAIOrder('order_xyz789');

console.log('Final NAV:', result.finalNav);
console.log('Gross profit:', result.grossProfit);
console.log('Completion rate:', (result.completionRate * 100).toFixed(1) + '%');
console.log('Penalty:', result.penaltyPercent + '%', '=', '$' + result.penaltyAmount.toFixed(2));
console.log('Net payout:', '$' + result.netPayout.toFixed(2));
console.log('Payout tx:', result.transactionHash);

方法签名

redeemAIOrder(orderId: string): Promise<AIRedemptionResult>

AIRedemptionResult 类型

interface AIRedemptionResult {
/** The updated order object with status 'redeemed'. */
order: AIOrder;

/** NAV at the time of redemption. */
finalNav: number;

/** Gross profit before penalty (finalNav - invested amount). */
grossProfit: number;

/** Penalty amount deducted for early withdrawal. 0 if the cycle completed or at a loss. */
penaltyAmount: number;

/** Penalty percentage applied (0-30). */
penaltyPercent: number;

/** Net amount paid out to the user (finalNav - penaltyAmount). */
netPayout: number;

/** Wallet address the payout was sent to. */
payoutAddress: string;

/** On-chain transaction hash for the payout. */
transactionHash: string;

/** Completion rate at the time of redemption (0 to 1). */
completionRate: number;

/** ISO 8601 timestamp of the redemption. */
redeemedAt: string;
}

提前赎回确认界面

在赎回之前,应向用户展示他们将承担的罚金预览。以下是一个确认页面示例。

import { useState, useEffect } from 'react';
import { OneEngineClient, DEFAULT_SHARE_RATES } from '@one_deploy/sdk';
import type { AIOrder, AIRedemptionResult } from '@one_deploy/sdk';

const MAX_PENALTY_PERCENT = 0.30;

interface WithdrawalConfirmProps {
engine: OneEngineClient;
order: AIOrder;
onComplete: (result: AIRedemptionResult) => void;
}

function WithdrawalConfirm({ engine, order, onComplete }: WithdrawalConfirmProps) {
const [submitting, setSubmitting] = useState(false);
const [error, setError] = useState<string | null>(null);

// Calculate estimated penalty
const now = new Date();
const created = new Date(order.createdAt);
const expires = new Date(order.expiresAt);

const totalDays = (expires.getTime() - created.getTime()) / (1000 * 60 * 60 * 24);
const elapsedDays = (now.getTime() - created.getTime()) / (1000 * 60 * 60 * 24);
const completionRate = Math.min(elapsedDays / totalDays, 1);

const grossProfit = order.currentNav - order.amount;
const penaltyPercent = grossProfit > 0
? MAX_PENALTY_PERCENT * (1 - completionRate)
: 0;
const penaltyAmount = Math.max(0, grossProfit) * penaltyPercent;
const estimatedPayout = order.currentNav - penaltyAmount;

const handleRedeem = async () => {
setSubmitting(true);
setError(null);
try {
const result = await engine.redeemAIOrder(order.id);
onComplete(result);
} catch (err) {
setError(err instanceof Error ? err.message : 'Redemption failed');
} finally {
setSubmitting(false);
}
};

return (
<View style={styles.container}>
<Text style={styles.heading}>Early Withdrawal</Text>
<Text style={styles.warning}>
You are redeeming before the cycle ends. A penalty may apply.
</Text>

<View style={styles.details}>
<DetailRow label="Invested" value={`$${order.amount.toFixed(2)}`} />
<DetailRow label="Current NAV" value={`$${order.currentNav.toFixed(2)}`} />
<DetailRow label="Gross Profit" value={`$${grossProfit.toFixed(2)}`} />
<DetailRow
label="Cycle Progress"
value={`${(completionRate * 100).toFixed(1)}% (${elapsedDays.toFixed(0)} / ${totalDays.toFixed(0)} days)`}
/>
<DetailRow
label="Penalty"
value={`${(penaltyPercent * 100).toFixed(1)}% = $${penaltyAmount.toFixed(2)}`}
/>
<View style={styles.divider} />
<DetailRow
label="Estimated Payout"
value={`$${estimatedPayout.toFixed(2)}`}
bold
/>
</View>

{error && <Text style={styles.error}>{error}</Text>}

<Pressable
onPress={handleRedeem}
disabled={submitting}
style={styles.redeemButton}
>
<Text style={styles.redeemButtonText}>
{submitting ? 'Processing...' : 'Confirm Withdrawal'}
</Text>
</Pressable>

<Text style={styles.disclaimer}>
Final amounts are calculated at the time of execution and may differ
slightly from the estimates shown above due to NAV changes.
</Text>
</View>
);
}

function DetailRow({
label,
value,
bold,
}: {
label: string;
value: string;
bold?: boolean;
}) {
return (
<View style={styles.detailRow}>
<Text style={bold ? styles.boldLabel : styles.label}>{label}</Text>
<Text style={bold ? styles.boldValue : styles.value}>{value}</Text>
</View>
);
}

要点总结

  • 罚金仅适用于利润,绝不会扣除原始资本。
  • 如果订单处于亏损状态,全额返还当前 NAV,不收取罚金。
  • 最大罚金为毛利润的 30%,在完成率为 0% 时适用。
  • 罚金随周期进展向完成方向线性递减
  • 100% 完成时(周期结束),罚金为 0% -- 订单正常完成。
  • 罚金在赎回时刻计算 -- 预览中显示的数值为估算值。

后续步骤