mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-10 06:20:58 +08:00
fix: initial balance calculation and UI improvements
- Fix initial balance using available_balance instead of total_equity - Fix WSMonitor nil pointer by starting market monitor before loading traders - Add strategy name display on traders list and dashboard pages - Various position sync and trading improvements
This commit is contained in:
@@ -807,7 +807,7 @@ function TraderDetailsPage({
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
className="flex items-center gap-4 text-sm"
|
||||
className="flex items-center gap-4 text-sm flex-wrap"
|
||||
style={{ color: '#848E9C' }}
|
||||
>
|
||||
<span>
|
||||
@@ -826,6 +826,20 @@ function TraderDetailsPage({
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
<span>•</span>
|
||||
<span>
|
||||
Exchange:{' '}
|
||||
<span className="font-semibold" style={{ color: '#EAECEF' }}>
|
||||
{selectedTrader.exchange_id?.toUpperCase() || 'N/A'}
|
||||
</span>
|
||||
</span>
|
||||
<span>•</span>
|
||||
<span>
|
||||
Strategy:{' '}
|
||||
<span className="font-semibold" style={{ color: '#F0B90B' }}>
|
||||
{selectedTrader.strategy_name || 'No Strategy'}
|
||||
</span>
|
||||
</span>
|
||||
{status && (
|
||||
<>
|
||||
<span>•</span>
|
||||
|
||||
@@ -368,7 +368,7 @@ export function TraderConfigModal({
|
||||
selectedStrategy.config.coin_source.source_type === 'oi_top' ? 'OI Top' : '混合'}
|
||||
</div>
|
||||
<div>
|
||||
风控等级: {((selectedStrategy.config.risk_control?.max_position_ratio || 0.3) * 100).toFixed(0)}% 仓位
|
||||
保证金上限: {((selectedStrategy.config.risk_control?.max_margin_usage || 0.9) * 100).toFixed(0)}%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -211,10 +211,10 @@ export function CoinSourceEditor({
|
||||
</span>
|
||||
<input
|
||||
type="number"
|
||||
value={config.coin_pool_limit || 30}
|
||||
value={config.coin_pool_limit || 10}
|
||||
onChange={(e) =>
|
||||
!disabled &&
|
||||
onChange({ ...config, coin_pool_limit: parseInt(e.target.value) || 30 })
|
||||
onChange({ ...config, coin_pool_limit: parseInt(e.target.value) || 10 })
|
||||
}
|
||||
disabled={disabled}
|
||||
min={1}
|
||||
|
||||
@@ -19,15 +19,24 @@ export function RiskControlEditor({
|
||||
positionLimits: { zh: '仓位限制', en: 'Position Limits' },
|
||||
maxPositions: { zh: '最大持仓数量', en: 'Max Positions' },
|
||||
maxPositionsDesc: { zh: '同时持有的最大币种数量', en: 'Maximum coins held simultaneously' },
|
||||
btcEthLeverage: { zh: 'BTC/ETH 最大杠杆', en: 'BTC/ETH Max Leverage' },
|
||||
altcoinLeverage: { zh: '山寨币最大杠杆', en: 'Altcoin Max Leverage' },
|
||||
// Trading leverage (exchange leverage)
|
||||
tradingLeverage: { zh: '交易杠杆(交易所杠杆)', en: 'Trading Leverage (Exchange)' },
|
||||
btcEthLeverage: { zh: 'BTC/ETH 交易杠杆', en: 'BTC/ETH Trading Leverage' },
|
||||
btcEthLeverageDesc: { zh: '交易所开仓使用的杠杆倍数', en: 'Exchange leverage for opening positions' },
|
||||
altcoinLeverage: { zh: '山寨币交易杠杆', en: 'Altcoin Trading Leverage' },
|
||||
altcoinLeverageDesc: { zh: '交易所开仓使用的杠杆倍数', en: 'Exchange leverage for opening positions' },
|
||||
// Position value ratio (risk control) - CODE ENFORCED
|
||||
positionValueRatio: { zh: '仓位价值比例(代码强制)', en: 'Position Value Ratio (CODE ENFORCED)' },
|
||||
positionValueRatioDesc: { zh: '单仓位名义价值 / 账户净值,由代码强制执行', en: 'Position notional value / equity, enforced by code' },
|
||||
btcEthPositionValueRatio: { zh: 'BTC/ETH 仓位价值比例', en: 'BTC/ETH Position Value Ratio' },
|
||||
btcEthPositionValueRatioDesc: { zh: '单仓最大名义价值 = 净值 × 此值(代码强制)', en: 'Max position value = equity × this ratio (CODE ENFORCED)' },
|
||||
altcoinPositionValueRatio: { zh: '山寨币仓位价值比例', en: 'Altcoin Position Value Ratio' },
|
||||
altcoinPositionValueRatioDesc: { zh: '单仓最大名义价值 = 净值 × 此值(代码强制)', en: 'Max position value = equity × this ratio (CODE ENFORCED)' },
|
||||
riskParameters: { zh: '风险参数', en: 'Risk Parameters' },
|
||||
minRiskReward: { zh: '最小风险回报比', en: 'Min Risk/Reward Ratio' },
|
||||
minRiskRewardDesc: { zh: '开仓要求的最低盈亏比', en: 'Minimum profit ratio for opening' },
|
||||
maxMarginUsage: { zh: '最大保证金使用率', en: 'Max Margin Usage' },
|
||||
maxMarginUsageDesc: { zh: '保证金使用率上限', en: 'Maximum margin utilization' },
|
||||
maxPositionRatio: { zh: '单币最大仓位比', en: 'Max Position Ratio' },
|
||||
maxPositionRatioDesc: { zh: '相对账户净值的倍数', en: 'Multiple of account equity' },
|
||||
maxMarginUsage: { zh: '最大保证金使用率(代码强制)', en: 'Max Margin Usage (CODE ENFORCED)' },
|
||||
maxMarginUsageDesc: { zh: '保证金使用率上限,由代码强制执行', en: 'Maximum margin utilization, enforced by code' },
|
||||
entryRequirements: { zh: '开仓要求', en: 'Entry Requirements' },
|
||||
minPositionSize: { zh: '最小开仓金额', en: 'Min Position Size' },
|
||||
minPositionSizeDesc: { zh: 'USDT 最小名义价值', en: 'Minimum notional value in USDT' },
|
||||
@@ -57,7 +66,7 @@ export function RiskControlEditor({
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div className="grid grid-cols-1 gap-4 mb-4">
|
||||
<div
|
||||
className="p-4 rounded-lg"
|
||||
style={{ background: '#0B0E11', border: '1px solid #2B3139' }}
|
||||
@@ -70,14 +79,14 @@ export function RiskControlEditor({
|
||||
</p>
|
||||
<input
|
||||
type="number"
|
||||
value={config.max_positions}
|
||||
value={config.max_positions ?? 3}
|
||||
onChange={(e) =>
|
||||
updateField('max_positions', parseInt(e.target.value) || 3)
|
||||
}
|
||||
disabled={disabled}
|
||||
min={1}
|
||||
max={10}
|
||||
className="w-full px-3 py-2 rounded"
|
||||
className="w-32 px-3 py-2 rounded"
|
||||
style={{
|
||||
background: '#1E2329',
|
||||
border: '1px solid #2B3139',
|
||||
@@ -85,7 +94,15 @@ export function RiskControlEditor({
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Trading Leverage (Exchange) */}
|
||||
<div className="mb-2">
|
||||
<p className="text-xs font-medium mb-2" style={{ color: '#F0B90B' }}>
|
||||
{t('tradingLeverage')}
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4 mb-4">
|
||||
<div
|
||||
className="p-4 rounded-lg"
|
||||
style={{ background: '#0B0E11', border: '1px solid #2B3139' }}
|
||||
@@ -93,10 +110,13 @@ export function RiskControlEditor({
|
||||
<label className="block text-sm mb-1" style={{ color: '#EAECEF' }}>
|
||||
{t('btcEthLeverage')}
|
||||
</label>
|
||||
<p className="text-xs mb-2" style={{ color: '#848E9C' }}>
|
||||
{t('btcEthLeverageDesc')}
|
||||
</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="range"
|
||||
value={config.btc_eth_max_leverage}
|
||||
value={config.btc_eth_max_leverage ?? 5}
|
||||
onChange={(e) =>
|
||||
updateField('btc_eth_max_leverage', parseInt(e.target.value))
|
||||
}
|
||||
@@ -109,7 +129,7 @@ export function RiskControlEditor({
|
||||
className="w-12 text-center font-mono"
|
||||
style={{ color: '#F0B90B' }}
|
||||
>
|
||||
{config.btc_eth_max_leverage}x
|
||||
{config.btc_eth_max_leverage ?? 5}x
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -121,10 +141,13 @@ export function RiskControlEditor({
|
||||
<label className="block text-sm mb-1" style={{ color: '#EAECEF' }}>
|
||||
{t('altcoinLeverage')}
|
||||
</label>
|
||||
<p className="text-xs mb-2" style={{ color: '#848E9C' }}>
|
||||
{t('altcoinLeverageDesc')}
|
||||
</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="range"
|
||||
value={config.altcoin_max_leverage}
|
||||
value={config.altcoin_max_leverage ?? 5}
|
||||
onChange={(e) =>
|
||||
updateField('altcoin_max_leverage', parseInt(e.target.value))
|
||||
}
|
||||
@@ -137,7 +160,82 @@ export function RiskControlEditor({
|
||||
className="w-12 text-center font-mono"
|
||||
style={{ color: '#F0B90B' }}
|
||||
>
|
||||
{config.altcoin_max_leverage}x
|
||||
{config.altcoin_max_leverage ?? 5}x
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Position Value Ratio (Risk Control - CODE ENFORCED) */}
|
||||
<div className="mb-2">
|
||||
<p className="text-xs font-medium" style={{ color: '#0ECB81' }}>
|
||||
{t('positionValueRatio')}
|
||||
</p>
|
||||
<p className="text-xs mt-1" style={{ color: '#848E9C' }}>
|
||||
{t('positionValueRatioDesc')}
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div
|
||||
className="p-4 rounded-lg"
|
||||
style={{ background: '#0B0E11', border: '1px solid #0ECB81' }}
|
||||
>
|
||||
<label className="block text-sm mb-1" style={{ color: '#EAECEF' }}>
|
||||
{t('btcEthPositionValueRatio')}
|
||||
</label>
|
||||
<p className="text-xs mb-2" style={{ color: '#848E9C' }}>
|
||||
{t('btcEthPositionValueRatioDesc')}
|
||||
</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="range"
|
||||
value={config.btc_eth_max_position_value_ratio ?? 5}
|
||||
onChange={(e) =>
|
||||
updateField('btc_eth_max_position_value_ratio', parseFloat(e.target.value))
|
||||
}
|
||||
disabled={disabled}
|
||||
min={0.5}
|
||||
max={10}
|
||||
step={0.5}
|
||||
className="flex-1 accent-green-500"
|
||||
/>
|
||||
<span
|
||||
className="w-12 text-center font-mono"
|
||||
style={{ color: '#0ECB81' }}
|
||||
>
|
||||
{config.btc_eth_max_position_value_ratio ?? 5}x
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="p-4 rounded-lg"
|
||||
style={{ background: '#0B0E11', border: '1px solid #0ECB81' }}
|
||||
>
|
||||
<label className="block text-sm mb-1" style={{ color: '#EAECEF' }}>
|
||||
{t('altcoinPositionValueRatio')}
|
||||
</label>
|
||||
<p className="text-xs mb-2" style={{ color: '#848E9C' }}>
|
||||
{t('altcoinPositionValueRatioDesc')}
|
||||
</p>
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="range"
|
||||
value={config.altcoin_max_position_value_ratio ?? 1}
|
||||
onChange={(e) =>
|
||||
updateField('altcoin_max_position_value_ratio', parseFloat(e.target.value))
|
||||
}
|
||||
disabled={disabled}
|
||||
min={0.5}
|
||||
max={10}
|
||||
step={0.5}
|
||||
className="flex-1 accent-green-500"
|
||||
/>
|
||||
<span
|
||||
className="w-12 text-center font-mono"
|
||||
style={{ color: '#0ECB81' }}
|
||||
>
|
||||
{config.altcoin_max_position_value_ratio ?? 1}x
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -153,7 +251,7 @@ export function RiskControlEditor({
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div
|
||||
className="p-4 rounded-lg"
|
||||
style={{ background: '#0B0E11', border: '1px solid #2B3139' }}
|
||||
@@ -168,7 +266,7 @@ export function RiskControlEditor({
|
||||
<span style={{ color: '#848E9C' }}>1:</span>
|
||||
<input
|
||||
type="number"
|
||||
value={config.min_risk_reward_ratio}
|
||||
value={config.min_risk_reward_ratio ?? 3}
|
||||
onChange={(e) =>
|
||||
updateField('min_risk_reward_ratio', parseFloat(e.target.value) || 3)
|
||||
}
|
||||
@@ -188,7 +286,7 @@ export function RiskControlEditor({
|
||||
|
||||
<div
|
||||
className="p-4 rounded-lg"
|
||||
style={{ background: '#0B0E11', border: '1px solid #2B3139' }}
|
||||
style={{ background: '#0B0E11', border: '1px solid #0ECB81' }}
|
||||
>
|
||||
<label className="block text-sm mb-1" style={{ color: '#EAECEF' }}>
|
||||
{t('maxMarginUsage')}
|
||||
@@ -199,51 +297,17 @@ export function RiskControlEditor({
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="range"
|
||||
value={config.max_margin_usage * 100}
|
||||
value={(config.max_margin_usage ?? 0.9) * 100}
|
||||
onChange={(e) =>
|
||||
updateField('max_margin_usage', parseInt(e.target.value) / 100)
|
||||
}
|
||||
disabled={disabled}
|
||||
min={10}
|
||||
max={100}
|
||||
className="flex-1 accent-red-500"
|
||||
className="flex-1 accent-green-500"
|
||||
/>
|
||||
<span className="w-12 text-center font-mono" style={{ color: '#F6465D' }}>
|
||||
{Math.round(config.max_margin_usage * 100)}%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="p-4 rounded-lg"
|
||||
style={{ background: '#0B0E11', border: '1px solid #2B3139' }}
|
||||
>
|
||||
<label className="block text-sm mb-1" style={{ color: '#EAECEF' }}>
|
||||
{t('maxPositionRatio')}
|
||||
</label>
|
||||
<p className="text-xs mb-2" style={{ color: '#848E9C' }}>
|
||||
{t('maxPositionRatioDesc')}
|
||||
</p>
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
type="number"
|
||||
value={config.max_position_ratio}
|
||||
onChange={(e) =>
|
||||
updateField('max_position_ratio', parseFloat(e.target.value) || 1.5)
|
||||
}
|
||||
disabled={disabled}
|
||||
min={0.5}
|
||||
max={5}
|
||||
step={0.1}
|
||||
className="w-20 px-3 py-2 rounded"
|
||||
style={{
|
||||
background: '#1E2329',
|
||||
border: '1px solid #2B3139',
|
||||
color: '#EAECEF',
|
||||
}}
|
||||
/>
|
||||
<span className="ml-2" style={{ color: '#848E9C' }}>
|
||||
x
|
||||
<span className="w-12 text-center font-mono" style={{ color: '#0ECB81' }}>
|
||||
{Math.round((config.max_margin_usage ?? 0.9) * 100)}%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -273,7 +337,7 @@ export function RiskControlEditor({
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
type="number"
|
||||
value={config.min_position_size}
|
||||
value={config.min_position_size ?? 12}
|
||||
onChange={(e) =>
|
||||
updateField('min_position_size', parseFloat(e.target.value) || 12)
|
||||
}
|
||||
@@ -306,7 +370,7 @@ export function RiskControlEditor({
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="range"
|
||||
value={config.min_confidence}
|
||||
value={config.min_confidence ?? 75}
|
||||
onChange={(e) =>
|
||||
updateField('min_confidence', parseInt(e.target.value))
|
||||
}
|
||||
@@ -316,7 +380,7 @@ export function RiskControlEditor({
|
||||
className="flex-1 accent-green-500"
|
||||
/>
|
||||
<span className="w-12 text-center font-mono" style={{ color: '#0ECB81' }}>
|
||||
{config.min_confidence}
|
||||
{config.min_confidence ?? 75}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -692,12 +692,42 @@ export function ExchangeConfigModal({
|
||||
{/* Aster 交易所的字段 */}
|
||||
{selectedExchange.id === 'aster' && (
|
||||
<>
|
||||
{/* API Pro 代理钱包说明 banner */}
|
||||
<div
|
||||
className="p-3 rounded mb-4"
|
||||
style={{
|
||||
background: 'rgba(240, 185, 11, 0.1)',
|
||||
border: '1px solid rgba(240, 185, 11, 0.3)',
|
||||
}}
|
||||
>
|
||||
<div className="flex items-start gap-2">
|
||||
<span style={{ color: '#F0B90B', fontSize: '16px' }}>
|
||||
🔐
|
||||
</span>
|
||||
<div className="flex-1">
|
||||
<div
|
||||
className="text-sm font-semibold mb-1"
|
||||
style={{ color: '#F0B90B' }}
|
||||
>
|
||||
{t('asterApiProTitle', language)}
|
||||
</div>
|
||||
<div
|
||||
className="text-xs"
|
||||
style={{ color: '#848E9C', lineHeight: '1.5' }}
|
||||
>
|
||||
{t('asterApiProDesc', language)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 主钱包地址 */}
|
||||
<div>
|
||||
<label
|
||||
className="block text-sm font-semibold mb-2 flex items-center gap-2"
|
||||
style={{ color: '#EAECEF' }}
|
||||
>
|
||||
{t('user', language)}
|
||||
{t('asterUserLabel', language)}
|
||||
<Tooltip content={t('asterUserDesc', language)}>
|
||||
<HelpCircle
|
||||
className="w-4 h-4 cursor-help"
|
||||
@@ -709,7 +739,7 @@ export function ExchangeConfigModal({
|
||||
type="text"
|
||||
value={asterUser}
|
||||
onChange={(e) => setAsterUser(e.target.value)}
|
||||
placeholder={t('enterUser', language)}
|
||||
placeholder={t('enterAsterUser', language)}
|
||||
className="w-full px-3 py-2 rounded"
|
||||
style={{
|
||||
background: '#0B0E11',
|
||||
@@ -718,14 +748,21 @@ export function ExchangeConfigModal({
|
||||
}}
|
||||
required
|
||||
/>
|
||||
<div
|
||||
className="text-xs mt-1"
|
||||
style={{ color: '#848E9C' }}
|
||||
>
|
||||
{t('asterUserDesc', language)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* API Pro 代理钱包地址 */}
|
||||
<div>
|
||||
<label
|
||||
className="block text-sm font-semibold mb-2 flex items-center gap-2"
|
||||
style={{ color: '#EAECEF' }}
|
||||
>
|
||||
{t('signer', language)}
|
||||
{t('asterSignerLabel', language)}
|
||||
<Tooltip content={t('asterSignerDesc', language)}>
|
||||
<HelpCircle
|
||||
className="w-4 h-4 cursor-help"
|
||||
@@ -737,7 +774,7 @@ export function ExchangeConfigModal({
|
||||
type="text"
|
||||
value={asterSigner}
|
||||
onChange={(e) => setAsterSigner(e.target.value)}
|
||||
placeholder={t('enterSigner', language)}
|
||||
placeholder={t('enterAsterSigner', language)}
|
||||
className="w-full px-3 py-2 rounded"
|
||||
style={{
|
||||
background: '#0B0E11',
|
||||
@@ -746,14 +783,21 @@ export function ExchangeConfigModal({
|
||||
}}
|
||||
required
|
||||
/>
|
||||
<div
|
||||
className="text-xs mt-1"
|
||||
style={{ color: '#848E9C' }}
|
||||
>
|
||||
{t('asterSignerDesc', language)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* API Pro 代理钱包私钥 */}
|
||||
<div>
|
||||
<label
|
||||
className="block text-sm font-semibold mb-2 flex items-center gap-2"
|
||||
style={{ color: '#EAECEF' }}
|
||||
>
|
||||
{t('privateKey', language)}
|
||||
{t('asterPrivateKeyLabel', language)}
|
||||
<Tooltip content={t('asterPrivateKeyDesc', language)}>
|
||||
<HelpCircle
|
||||
className="w-4 h-4 cursor-help"
|
||||
@@ -765,7 +809,7 @@ export function ExchangeConfigModal({
|
||||
type="password"
|
||||
value={asterPrivateKey}
|
||||
onChange={(e) => setAsterPrivateKey(e.target.value)}
|
||||
placeholder={t('enterPrivateKey', language)}
|
||||
placeholder={t('enterAsterPrivateKey', language)}
|
||||
className="w-full px-3 py-2 rounded"
|
||||
style={{
|
||||
background: '#0B0E11',
|
||||
@@ -774,6 +818,12 @@ export function ExchangeConfigModal({
|
||||
}}
|
||||
required
|
||||
/>
|
||||
<div
|
||||
className="text-xs mt-1"
|
||||
style={{ color: '#848E9C' }}
|
||||
>
|
||||
{t('asterPrivateKeyDesc', language)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -75,6 +75,7 @@ export function TradersGrid({
|
||||
trader.ai_model.split('_').pop() || trader.ai_model
|
||||
)}{' '}
|
||||
Model • {trader.exchange_id?.toUpperCase()}
|
||||
<span style={{ color: '#F0B90B' }}> • {trader.strategy_name || 'No Strategy'}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -352,14 +352,24 @@ export const translations = {
|
||||
enterHyperliquidMainWalletAddress: 'Enter Main wallet address',
|
||||
hyperliquidMainWalletAddressDesc:
|
||||
'Main wallet address that holds your trading funds (never expose its private key)',
|
||||
// Aster API Pro Configuration
|
||||
asterApiProTitle: 'Aster API Pro Wallet Configuration',
|
||||
asterApiProDesc:
|
||||
'Use API Pro wallet for secure trading: API wallet signs transactions, main wallet holds funds (never expose main wallet private key)',
|
||||
asterUserDesc:
|
||||
'Main wallet address - The EVM wallet address you use to log in to Aster (Note: Only EVM wallets are supported, Solana wallets are not supported)',
|
||||
'Main wallet address - The EVM wallet address you use to log in to Aster (Note: Only EVM wallets are supported)',
|
||||
asterSignerDesc:
|
||||
'API wallet address - Generate from https://www.asterdex.com/en/api-wallet',
|
||||
'API Pro wallet address (0x...) - Generate from https://www.asterdex.com/en/api-wallet',
|
||||
asterPrivateKeyDesc:
|
||||
'API wallet private key - Get from https://www.asterdex.com/en/api-wallet (only used locally for signing, never transmitted)',
|
||||
'API Pro wallet private key - Get from https://www.asterdex.com/en/api-wallet (only used locally for signing, never transmitted)',
|
||||
asterUsdtWarning:
|
||||
'Important: Aster only tracks USDT balance. Please ensure you use USDT as margin currency to avoid P&L calculation errors caused by price fluctuations of other assets (BNB, ETH, etc.)',
|
||||
asterUserLabel: 'Main Wallet Address',
|
||||
asterSignerLabel: 'API Pro Wallet Address',
|
||||
asterPrivateKeyLabel: 'API Pro Wallet Private Key',
|
||||
enterAsterUser: 'Enter main wallet address (0x...)',
|
||||
enterAsterSigner: 'Enter API Pro wallet address (0x...)',
|
||||
enterAsterPrivateKey: 'Enter API Pro wallet private key',
|
||||
|
||||
// LIGHTER Configuration
|
||||
lighterWalletAddress: 'L1 Wallet Address',
|
||||
@@ -1347,14 +1357,24 @@ export const translations = {
|
||||
enterHyperliquidMainWalletAddress: '输入主钱包地址',
|
||||
hyperliquidMainWalletAddressDesc:
|
||||
'持有交易资金的主钱包地址(永不暴露其私钥)',
|
||||
// Aster API Pro 配置
|
||||
asterApiProTitle: 'Aster API Pro 代理钱包配置',
|
||||
asterApiProDesc:
|
||||
'使用 API Pro 代理钱包安全交易:代理钱包用于签名交易,主钱包持有资金(永不暴露主钱包私钥)',
|
||||
asterUserDesc:
|
||||
'主钱包地址 - 您用于登录 Aster 的 EVM 钱包地址(注意:仅支持 EVM 钱包,不支持 Solana 钱包)',
|
||||
'主钱包地址 - 您用于登录 Aster 的 EVM 钱包地址(仅支持 EVM 钱包)',
|
||||
asterSignerDesc:
|
||||
'API 钱包地址 - 从 https://www.asterdex.com/zh-CN/api-wallet 生成',
|
||||
'API Pro 代理钱包地址 (0x...) - 从 https://www.asterdex.com/zh-CN/api-wallet 生成',
|
||||
asterPrivateKeyDesc:
|
||||
'API 钱包私钥 - 从 https://www.asterdex.com/zh-CN/api-wallet 获取(仅在本地用于签名,不会被传输)',
|
||||
'API Pro 代理钱包私钥 - 从 https://www.asterdex.com/zh-CN/api-wallet 获取(仅在本地用于签名,不会被传输)',
|
||||
asterUsdtWarning:
|
||||
'重要提示:Aster 仅统计 USDT 余额。请确保您使用 USDT 作为保证金币种,避免其他资产(BNB、ETH等)的价格波动导致盈亏统计错误',
|
||||
asterUserLabel: '主钱包地址',
|
||||
asterSignerLabel: 'API Pro 代理钱包地址',
|
||||
asterPrivateKeyLabel: 'API Pro 代理钱包私钥',
|
||||
enterAsterUser: '输入主钱包地址 (0x...)',
|
||||
enterAsterSigner: '输入 API Pro 代理钱包地址 (0x...)',
|
||||
enterAsterPrivateKey: '输入 API Pro 代理钱包私钥',
|
||||
|
||||
// LIGHTER 配置
|
||||
lighterWalletAddress: 'L1 錢包地址',
|
||||
|
||||
@@ -91,6 +91,8 @@ export interface TraderInfo {
|
||||
ai_model: string
|
||||
exchange_id?: string
|
||||
is_running?: boolean
|
||||
strategy_id?: string
|
||||
strategy_name?: string
|
||||
custom_prompt?: string
|
||||
use_coin_pool?: boolean
|
||||
use_oi_top?: boolean
|
||||
@@ -437,12 +439,21 @@ export interface ExternalDataSource {
|
||||
}
|
||||
|
||||
export interface RiskControlConfig {
|
||||
// Max number of coins held simultaneously (CODE ENFORCED)
|
||||
max_positions: number;
|
||||
btc_eth_max_leverage: number;
|
||||
altcoin_max_leverage: number;
|
||||
min_risk_reward_ratio: number;
|
||||
max_margin_usage: number;
|
||||
max_position_ratio: number;
|
||||
min_position_size: number;
|
||||
min_confidence: number;
|
||||
|
||||
// Trading Leverage - exchange leverage for opening positions (AI guided)
|
||||
btc_eth_max_leverage: number; // BTC/ETH max exchange leverage
|
||||
altcoin_max_leverage: number; // Altcoin max exchange leverage
|
||||
|
||||
// Position Value Ratio - single position notional value / account equity (CODE ENFORCED)
|
||||
// Max position value = equity × this ratio
|
||||
btc_eth_max_position_value_ratio?: number; // default: 5 (BTC/ETH max position = 5x equity)
|
||||
altcoin_max_position_value_ratio?: number; // default: 1 (Altcoin max position = 1x equity)
|
||||
|
||||
// Risk Parameters
|
||||
max_margin_usage: number; // Max margin utilization, e.g. 0.9 = 90% (CODE ENFORCED)
|
||||
min_position_size: number; // Min position size in USDT (CODE ENFORCED)
|
||||
min_risk_reward_ratio: number; // Min take_profit / stop_loss ratio (AI guided)
|
||||
min_confidence: number; // Min AI confidence to open position (AI guided)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user