Add configurable data providers and localize frontend UI
This commit is contained in:
@@ -83,6 +83,7 @@ export default function LiveTradingApp() {
|
||||
const [serverMode, setServerMode] = useState(null); // 'live' | 'backtest' | null
|
||||
const [marketStatus, setMarketStatus] = useState(null); // { status, status_text, ... }
|
||||
const [virtualTime, setVirtualTime] = useState(null); // Virtual time from server (for mock mode)
|
||||
const [dataSources, setDataSources] = useState(null);
|
||||
|
||||
const clientRef = useRef(null);
|
||||
const containerRef = useRef(null);
|
||||
@@ -290,6 +291,9 @@ export default function LiveTradingApp() {
|
||||
if (state.server_mode) {
|
||||
setServerMode(state.server_mode);
|
||||
}
|
||||
if (state.data_sources) {
|
||||
setDataSources(state.data_sources);
|
||||
}
|
||||
// 检查是否是mock模式
|
||||
const isMockMode = state.is_mock_mode === true;
|
||||
if (state.market_status) {
|
||||
@@ -365,6 +369,12 @@ export default function LiveTradingApp() {
|
||||
}
|
||||
},
|
||||
|
||||
data_sources_update: (e) => {
|
||||
if (e.data_sources) {
|
||||
setDataSources(e.data_sources);
|
||||
}
|
||||
},
|
||||
|
||||
// Real-time price updates
|
||||
price_update: (e) => {
|
||||
try {
|
||||
@@ -864,6 +874,14 @@ export default function LiveTradingApp() {
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
{dataSources?.last_success?.prices && (
|
||||
<>
|
||||
<span className="status-sep">·</span>
|
||||
<span className="market-text backtest">
|
||||
DATA {String(dataSources.last_success.prices).toUpperCase()}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
<span className="status-sep">·</span>
|
||||
<span className="time-text">{lastUpdate.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false })}</span>
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import Header from './Header.jsx';
|
||||
|
||||
export default function AboutModal({ onClose }) {
|
||||
const [isClosing, setIsClosing] = useState(false);
|
||||
const [language, setLanguage] = useState('en'); // 'en' or 'zh'
|
||||
const [language] = useState('zh');
|
||||
|
||||
const handleClose = () => {
|
||||
setIsClosing(true);
|
||||
@@ -188,79 +188,14 @@ export default function AboutModal({ onClose }) {
|
||||
|
||||
{/* Content */}
|
||||
<div style={contentStyle} onClick={(e) => e.stopPropagation()}>
|
||||
{/* Language Switch */}
|
||||
<div style={languageSwitchStyle}>
|
||||
<span
|
||||
style={getLangStyle(language === 'zh')}
|
||||
onClick={() => setLanguage('zh')}
|
||||
style={getLangStyle(true)}
|
||||
>
|
||||
中文
|
||||
</span>
|
||||
<span style={{ padding: '0 4px', color: '#999' }}>|</span>
|
||||
<span
|
||||
style={getLangStyle(language === 'en')}
|
||||
onClick={() => setLanguage('en')}
|
||||
>
|
||||
EN
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{language === 'en' ? (
|
||||
// English Content
|
||||
<>
|
||||
|
||||
<div style={{ marginBottom: '40px', fontSize: '15px', fontWeight: 600 }}>
|
||||
{content.en.question}
|
||||
<span style={highlight}>{content.en.questionHighlight}</span>
|
||||
{content.en.questionEnd}
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '30px' }}>
|
||||
{content.en.intro}
|
||||
<span style={highlight}>{content.en.introHighlight1}</span>
|
||||
{content.en.introContinue}
|
||||
<span style={highlight}>{content.en.introHighlight2}</span>
|
||||
{content.en.introContinue2}
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '25px' }}>
|
||||
<span style={highlight}>{content.en.point1Highlight}</span>
|
||||
{content.en.point1}
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '25px' }}>
|
||||
<span style={highlight}>{content.en.point2Highlight}</span>
|
||||
{content.en.point2}
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '40px' }}>
|
||||
<span style={highlight}>{content.en.point3Highlight}</span>
|
||||
{content.en.point3}
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '25px', opacity: 0.7 }}>
|
||||
Everything is fully open-source. Built on{' '}
|
||||
<a
|
||||
href="https://github.com/agentscope-ai"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={linkStyle}
|
||||
>
|
||||
AgentScope
|
||||
</a>
|
||||
, using{' '}
|
||||
<a
|
||||
href="https://github.com/agentscope-ai/ReMe"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={linkStyle}
|
||||
>
|
||||
ReMe
|
||||
</a>
|
||||
{' '}for memory management.
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
// Chinese Content
|
||||
<>
|
||||
<div style={{ marginBottom: '30px' }}>
|
||||
@@ -309,7 +244,7 @@ export default function AboutModal({ onClose }) {
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '10px', opacity: 0.7 }}>
|
||||
我们已经在github上开源。
|
||||
我们已经在 GitHub 上开源。
|
||||
</div>
|
||||
<div style={{ marginBottom: '25px', opacity: 0.7 }}>
|
||||
EvoTraders 基于{' '}
|
||||
@@ -337,7 +272,6 @@ export default function AboutModal({ onClose }) {
|
||||
你可以在此找到完整项目与示例:
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div style={{ marginTop: '40px' }}>
|
||||
<a
|
||||
@@ -351,11 +285,10 @@ export default function AboutModal({ onClose }) {
|
||||
</div>
|
||||
|
||||
<div style={closeHintStyle} onClick={handleClose}>
|
||||
{language === 'en' ? 'Click here to close' : '点击此处关闭'}
|
||||
点击此处关闭
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ export default function AgentCard({ agent, onClose, isClosing }) {
|
||||
</div>
|
||||
{rankMedal && !isPortfolioManager && (
|
||||
<div style={{ fontSize: 18 }}>
|
||||
{rankMedal.emoji} Rank #{agent.rank}
|
||||
{rankMedal.emoji} 第 {agent.rank} 名
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@@ -188,7 +188,7 @@ export default function AgentCard({ agent, onClose, isClosing }) {
|
||||
position: 'relative',
|
||||
cursor: 'help'
|
||||
}}
|
||||
title={`Model: ${agent.modelName}\nProvider: ${modelInfo.provider}`}>
|
||||
title={`模型:${agent.modelName}\n提供方:${modelInfo.provider}`}>
|
||||
<div style={{
|
||||
fontSize: 10,
|
||||
fontWeight: 700,
|
||||
@@ -272,7 +272,7 @@ export default function AgentCard({ agent, onClose, isClosing }) {
|
||||
lineHeight: 1,
|
||||
marginBottom: 2
|
||||
}}>
|
||||
{overallWinRate != null ? `${(overallWinRate * 100).toFixed(1)}%` : 'N/A'}
|
||||
{overallWinRate != null ? `${(overallWinRate * 100).toFixed(1)}%` : '暂无'}
|
||||
</div>
|
||||
<div style={{
|
||||
fontSize: 9,
|
||||
@@ -318,7 +318,7 @@ export default function AgentCard({ agent, onClose, isClosing }) {
|
||||
marginBottom: 2,
|
||||
lineHeight: 1
|
||||
}}>
|
||||
{bullWinRate != null ? `${(bullWinRate * 100).toFixed(1)}%` : 'N/A'}
|
||||
{bullWinRate != null ? `${(bullWinRate * 100).toFixed(1)}%` : '暂无'}
|
||||
</div>
|
||||
<div style={{
|
||||
fontSize: 9,
|
||||
@@ -355,7 +355,7 @@ export default function AgentCard({ agent, onClose, isClosing }) {
|
||||
marginBottom: 2,
|
||||
lineHeight: 1
|
||||
}}>
|
||||
{bearWinRate != null ? `${(bearWinRate * 100).toFixed(1)}%` : 'N/A'}
|
||||
{bearWinRate != null ? `${(bearWinRate * 100).toFixed(1)}%` : '暂无'}
|
||||
</div>
|
||||
<div style={{
|
||||
fontSize: 9,
|
||||
@@ -439,7 +439,7 @@ export default function AgentCard({ agent, onClose, isClosing }) {
|
||||
fontSize: 8,
|
||||
color: '#555555'
|
||||
}}>
|
||||
{signal.date?.substring(5, 10) || 'N/A'}
|
||||
{signal.date?.substring(5, 10) || '暂无'}
|
||||
</div>
|
||||
<div style={{
|
||||
fontSize: resultFontSize,
|
||||
@@ -514,4 +514,3 @@ export default function AgentCard({ agent, onClose, isClosing }) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -525,7 +525,7 @@ function MessageItem({ message, itemId, isHighlighted, getAgentModelInfo }) {
|
||||
|
||||
const colors = message.agent === 'Memory' ? MESSAGE_COLORS.memory :
|
||||
getAgentColors(message.agentId, message.agent);
|
||||
const title = message.agent === 'Memory' ? '记忆' : message.agent || 'AGENT';
|
||||
const title = message.agent === 'Memory' ? '记忆' : message.agent || '智能体';
|
||||
|
||||
const agentModelData = message.agentId && getAgentModelInfo ?
|
||||
getAgentModelInfo(message.agentId) :
|
||||
|
||||
@@ -13,24 +13,24 @@ export default function PerformanceView({ leaderboard }) {
|
||||
{/* Agent Performance Section */}
|
||||
<div className="section">
|
||||
<div className="section-header">
|
||||
<h2 className="section-title">Agent Performance - Signal Accuracy</h2>
|
||||
<h2 className="section-title">分析师表现 - 信号准确率</h2>
|
||||
</div>
|
||||
|
||||
{rankedAgents.length === 0 ? (
|
||||
<div className="empty-state">No leaderboard data available</div>
|
||||
<div className="empty-state">暂无排行榜数据</div>
|
||||
) : (
|
||||
<div className="table-wrapper">
|
||||
<table className="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Rank</th>
|
||||
<th>Agent</th>
|
||||
<th>Win Rate</th>
|
||||
<th>Bull Signals</th>
|
||||
<th>Bull Win Rate</th>
|
||||
<th>Bear Signals</th>
|
||||
<th>Bear Win Rate</th>
|
||||
<th>Total Signals</th>
|
||||
<th>排名</th>
|
||||
<th>分析师</th>
|
||||
<th>胜率</th>
|
||||
<th>看涨信号</th>
|
||||
<th>看涨胜率</th>
|
||||
<th>看跌信号</th>
|
||||
<th>看跌胜率</th>
|
||||
<th>总信号数</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -66,27 +66,27 @@ export default function PerformanceView({ leaderboard }) {
|
||||
<div style={{ fontSize: 10, color: '#666666' }}>{agent.role}</div>
|
||||
</td>
|
||||
<td style={{ fontWeight: 700, color: overallColor }}>
|
||||
{overallWinRate != null ? `${(overallWinRate * 100).toFixed(1)}%` : 'N/A'}
|
||||
{overallWinRate != null ? `${(overallWinRate * 100).toFixed(1)}%` : '暂无'}
|
||||
</td>
|
||||
<td>
|
||||
<div style={{ fontSize: 12 }}>{bullTotal} signals</div>
|
||||
<div style={{ fontSize: 10, color: '#666666' }}>{bullWins} wins</div>
|
||||
<div style={{ fontSize: 12 }}>{bullTotal} 个信号</div>
|
||||
<div style={{ fontSize: 10, color: '#666666' }}>{bullWins} 次命中</div>
|
||||
{bullUnknown > 0 && (
|
||||
<div style={{ fontSize: 10, color: '#999999' }}>{bullUnknown} unknown</div>
|
||||
<div style={{ fontSize: 10, color: '#999999' }}>{bullUnknown} 条未判定</div>
|
||||
)}
|
||||
</td>
|
||||
<td style={{ color: bullWinRate != null ? (bullWinRate >= 0.5 ? '#00C853' : '#999999') : '#999999' }}>
|
||||
{bullWinRate != null ? `${(bullWinRate * 100).toFixed(1)}%` : 'N/A'}
|
||||
{bullWinRate != null ? `${(bullWinRate * 100).toFixed(1)}%` : '暂无'}
|
||||
</td>
|
||||
<td>
|
||||
<div style={{ fontSize: 12 }}>{bearTotal} signals</div>
|
||||
<div style={{ fontSize: 10, color: '#666666' }}>{bearWins} wins</div>
|
||||
<div style={{ fontSize: 12 }}>{bearTotal} 个信号</div>
|
||||
<div style={{ fontSize: 10, color: '#666666' }}>{bearWins} 次命中</div>
|
||||
{bearUnknown > 0 && (
|
||||
<div style={{ fontSize: 10, color: '#999999' }}>{bearUnknown} unknown</div>
|
||||
<div style={{ fontSize: 10, color: '#999999' }}>{bearUnknown} 条未判定</div>
|
||||
)}
|
||||
</td>
|
||||
<td style={{ color: bearWinRate != null ? (bearWinRate >= 0.5 ? '#00C853' : '#999999') : '#999999' }}>
|
||||
{bearWinRate != null ? `${(bearWinRate * 100).toFixed(1)}%` : 'N/A'}
|
||||
{bearWinRate != null ? `${(bearWinRate * 100).toFixed(1)}%` : '暂无'}
|
||||
</td>
|
||||
<td style={{ fontWeight: 700 }}>{totalSignals}</td>
|
||||
</tr>
|
||||
@@ -102,7 +102,7 @@ export default function PerformanceView({ leaderboard }) {
|
||||
{rankedAgents.length > 0 && rankedAgents.some(agent => agent.signals && agent.signals.length > 0) && (
|
||||
<div className="section" style={{ marginTop: 32 }}>
|
||||
<div className="section-header">
|
||||
<h2 className="section-title">Signal History</h2>
|
||||
<h2 className="section-title">信号历史</h2>
|
||||
</div>
|
||||
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(400px, 1fr))', gap: 20 }}>
|
||||
@@ -150,7 +150,7 @@ export default function PerformanceView({ leaderboard }) {
|
||||
const hasRealReturn = typeof realReturnValue === 'number' && Number.isFinite(realReturnValue);
|
||||
const realReturnDisplay = hasRealReturn
|
||||
? `${realReturnValue >= 0 ? '+' : ''}${(realReturnValue * 100).toFixed(2)}%`
|
||||
: 'Unknown';
|
||||
: '未判定';
|
||||
const realReturnColor = hasRealReturn
|
||||
? (realReturnValue >= 0 ? '#00C853' : '#FF1744')
|
||||
: '#999999';
|
||||
@@ -189,7 +189,7 @@ export default function PerformanceView({ leaderboard }) {
|
||||
color: isBull ? '#00C853' : isBear ? '#FF1744' : '#999999',
|
||||
fontSize: 12
|
||||
}}>
|
||||
{isBull ? 'Bull' : isBear ? 'Bear' : 'Neutral'}
|
||||
{isBull ? '看涨' : isBear ? '看跌' : '中性'}
|
||||
</span>
|
||||
{!isNeutral && (
|
||||
<span style={{
|
||||
@@ -222,7 +222,7 @@ export default function PerformanceView({ leaderboard }) {
|
||||
color: '#666666',
|
||||
textAlign: 'center'
|
||||
}}>
|
||||
Total: {sortedSignals.length} signals
|
||||
共 {sortedSignals.length} 条信号
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -233,4 +233,3 @@ export default function PerformanceView({ leaderboard }) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
|
||||
import { LLM_MODEL_LOGOS } from '../config/constants';
|
||||
|
||||
export default function RulesView() {
|
||||
const [language, setLanguage] = useState('en'); // 'en' or 'zh'
|
||||
const [language] = useState('zh');
|
||||
const [scale, setScale] = useState(1);
|
||||
const containerRef = useRef(null);
|
||||
const contentRef = useRef(null);
|
||||
@@ -197,19 +197,19 @@ export default function RulesView() {
|
||||
section2Title: "Agent 决策机制",
|
||||
|
||||
tradingProcess: "交易流程",
|
||||
tradingDesc: "Agents 进行日频交易并持续跟踪组合净值。每天最终交易决策前,agents 经历三个关键阶段:",
|
||||
tradingDesc: "智能体以日频进行交易并持续跟踪组合净值。每天最终交易决策前,会经历三个关键阶段:",
|
||||
|
||||
analysisPhase: "• 分析阶段",
|
||||
analysisDesc: "所有 agents 根据各自的工具和信息独立分析并形成判断。",
|
||||
analysisDesc: "所有智能体根据各自的工具和信息独立分析并形成判断。",
|
||||
|
||||
communicationPhase: "• 沟通阶段",
|
||||
commIntro: "提供了多种沟通渠道:1v1 私聊 / 1vN 通知 / NvN 会议",
|
||||
|
||||
decisionPhase: "• 决策阶段",
|
||||
decisionDesc: "由 portfolio manager 汇总所有信息,并给出最终的团队交易。analysts 给出的原始交易信号仅做个人维度的排名。",
|
||||
decisionDesc: "由投资经理汇总所有信息,并给出最终的团队交易决策。分析师给出的原始交易信号仅用于个人维度排名。",
|
||||
|
||||
reflectionTitle: "学习与进化",
|
||||
reflectionDesc: "Agents 根据当日实际收益反思决策、总结经验,并存入 ",
|
||||
reflectionDesc: "智能体根据当日实际收益反思决策、总结经验,并存入 ",
|
||||
remeLink: "ReMe",
|
||||
reflectionDesc2: " 记忆框架以持续改进。",
|
||||
|
||||
@@ -219,14 +219,14 @@ export default function RulesView() {
|
||||
chartDesc: "追踪组合收益曲线 vs. 基准策略(等权、市值加权、动量)。用于评估整体策略有效性。",
|
||||
|
||||
rankingTitle: "• 分析师排名",
|
||||
rankingDesc: "在 Trading Room 点击头像查看分析师表现(胜率、牛/熊市胜率)。用于了解哪些分析师提供最有价值的洞察。",
|
||||
rankingDesc: "在交易室点击头像查看分析师表现(胜率、牛/熊市胜率),用来了解哪些分析师提供了最有价值的洞察。",
|
||||
|
||||
statsTitle: "• 统计数据",
|
||||
statsDesc: "详细的持仓和交易历史。用于深入分析仓位管理和执行质量。",
|
||||
|
||||
callToAction: "在 ",
|
||||
callToAction: "可在 ",
|
||||
repoLink: "GitHub",
|
||||
callToAction2: " 上 fork 并自定义!"
|
||||
callToAction2: " 上 Fork 并自行定制。"
|
||||
}
|
||||
};
|
||||
|
||||
@@ -234,136 +234,14 @@ export default function RulesView() {
|
||||
<div ref={containerRef} style={containerStyle}>
|
||||
<div ref={contentRef} style={contentWrapperStyle}>
|
||||
<div style={innerContentStyle}>
|
||||
{/* Language Switch */}
|
||||
<div style={languageSwitchStyle}>
|
||||
<span
|
||||
style={getLangStyle(language === 'zh')}
|
||||
onClick={() => setLanguage('zh')}
|
||||
style={getLangStyle(true)}
|
||||
>
|
||||
中文
|
||||
</span>
|
||||
<span style={{ padding: '0 4px', color: '#999' }}>|</span>
|
||||
<span
|
||||
style={getLangStyle(language === 'en')}
|
||||
onClick={() => setLanguage('en')}
|
||||
>
|
||||
EN
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{language === 'en' ? (
|
||||
// English Content
|
||||
<>
|
||||
{/* Section 1: Agent Setup */}
|
||||
<div style={sectionTitleStyle}>{content.en.section1Title}</div>
|
||||
|
||||
{/* Roles */}
|
||||
<div style={{ marginBottom: '8px', fontSize: '12px' }}>
|
||||
<div style={{ marginBottom: '3px' }}>
|
||||
<span style={{ fontWeight: 600 }}>{content.en.pmRole}:</span> {content.en.pmDesc}
|
||||
</div>
|
||||
<div style={{ marginBottom: '3px' }}>
|
||||
<span style={{ fontWeight: 600 }}>{content.en.rmRole}:</span> {content.en.rmDesc}
|
||||
</div>
|
||||
<div style={{ marginBottom: '3px' }}>
|
||||
<span style={{ fontWeight: 600 }}>{content.en.analystsRole}:</span> {content.en.analystsDesc}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Analysts with AI Models */}
|
||||
<div style={{ marginLeft: '10px', marginBottom: '8px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '3px 14px', fontSize: '11px' }}>
|
||||
{content.en.analysts.map(analyst => {
|
||||
const logo = llmLogos.find(l => l.name === analyst.modelKey);
|
||||
return (
|
||||
<div key={analyst.name} style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '8px'
|
||||
}}>
|
||||
{logo && (
|
||||
<img
|
||||
src={logo.url}
|
||||
alt={logo.label}
|
||||
style={{
|
||||
height: '16px',
|
||||
width: 'auto',
|
||||
objectFit: 'contain'
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<span style={{ fontWeight: 600 }}>{analyst.name}</span>
|
||||
<span style={{ color: '#666' }}>- {analyst.model}</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '10px', fontSize: '11px', fontStyle: 'italic', opacity: 0.8 }}>
|
||||
{content.en.callToAction}
|
||||
<a
|
||||
href="https://github.com/agentscope-ai/agentscope-samples"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={linkStyle}
|
||||
>
|
||||
{content.en.repoLink}
|
||||
</a>
|
||||
{content.en.callToAction2}
|
||||
</div>
|
||||
|
||||
{/* Section 2: Agent Decision Mechanism */}
|
||||
<div style={sectionTitleStyle}>{content.en.section2Title}</div>
|
||||
|
||||
<div style={{ marginBottom: '6px' }}>
|
||||
<div style={{ fontWeight: 600, marginBottom: '3px' }}>{content.en.tradingProcess}</div>
|
||||
<div style={{ marginBottom: '6px', fontSize: '12px' }}>{content.en.tradingDesc}</div>
|
||||
|
||||
<div style={subsectionStyle}>
|
||||
<div style={{ marginBottom: '4px', fontSize: '12px' }}>
|
||||
<span style={highlight}>{content.en.analysisPhase.replace('• ', '')}:</span> {content.en.analysisDesc}
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '4px', fontSize: '12px' }}>
|
||||
<span style={highlight}>{content.en.communicationPhase.replace('• ', '')}:</span> {content.en.commIntro}
|
||||
</div>
|
||||
|
||||
<div style={{ fontSize: '12px' }}>
|
||||
<span style={highlight}>{content.en.decisionPhase.replace('• ', '')}:</span> {content.en.decisionDesc}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: '10px' }}>
|
||||
<div style={{ fontWeight: 600, marginBottom: '3px' }}>{content.en.reflectionTitle}</div>
|
||||
<div style={{ fontSize: '12px' }}>
|
||||
{content.en.reflectionDesc}
|
||||
<a
|
||||
href="https://github.com/agentscope-ai/ReMe"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={linkStyle}
|
||||
>
|
||||
{content.en.remeLink}
|
||||
</a>
|
||||
{content.en.reflectionDesc2}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Section 3: Performance Evaluation */}
|
||||
<div style={sectionTitleStyle}>{content.en.section3Title}</div>
|
||||
<div style={subsectionStyle}>
|
||||
<div style={{ marginBottom: '3px', fontSize: '12px' }}>
|
||||
<span style={{ fontWeight: 600 }}>{content.en.chartTitle.replace('• ', '')}:</span> {content.en.chartDesc}
|
||||
</div>
|
||||
<div style={{ marginBottom: '3px', fontSize: '12px' }}>
|
||||
<span style={{ fontWeight: 600 }}>{content.en.rankingTitle.replace('• ', '')}:</span> {content.en.rankingDesc}
|
||||
</div>
|
||||
<div style={{ fontSize: '12px' }}>
|
||||
<span style={{ fontWeight: 600 }}>{content.en.statsTitle.replace('• ', '')}:</span> {content.en.statsDesc}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
// Chinese Content
|
||||
<>
|
||||
{/* 第一部分:Agent 设定 */}
|
||||
@@ -475,7 +353,6 @@ export default function RulesView() {
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -243,7 +243,7 @@ export default function StatisticsView({ trades, holdings, stats, baseline_vw, e
|
||||
}}>
|
||||
{pmWinRateData?.winRate != null
|
||||
? `${(pmWinRateData.winRate * 100).toFixed(1)}%`
|
||||
: 'N/A'}
|
||||
: '暂无'}
|
||||
</div>
|
||||
{pmWinRateData && (
|
||||
<div style={{
|
||||
|
||||
@@ -132,7 +132,7 @@ export const AXIS_TICKS = 5;
|
||||
// WebSocket configuration
|
||||
export const WS_URL = import.meta.env.VITE_WS_URL || "ws://localhost:8765";
|
||||
|
||||
// Initial ticker symbols (MAG7 companies)
|
||||
// Initial ticker symbols for the production watchlist
|
||||
export const INITIAL_TICKERS = [
|
||||
{ symbol: "AAPL", price: null, change: null },
|
||||
{ symbol: "MSFT", price: null, change: null },
|
||||
@@ -140,6 +140,10 @@ export const INITIAL_TICKERS = [
|
||||
{ symbol: "AMZN", price: null, change: null },
|
||||
{ symbol: "NVDA", price: null, change: null },
|
||||
{ symbol: "META", price: null, change: null },
|
||||
{ symbol: "TSLA", price: null, change: null }
|
||||
{ symbol: "TSLA", price: null, change: null },
|
||||
{ symbol: "AMD", price: null, change: null },
|
||||
{ symbol: "NFLX", price: null, change: null },
|
||||
{ symbol: "AVGO", price: null, change: null },
|
||||
{ symbol: "PLTR", price: null, change: null },
|
||||
{ symbol: "COIN", price: null, change: null }
|
||||
];
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ export class ReadOnlyClient {
|
||||
this.reconnectAttempts = 0;
|
||||
this.reconnectDelay = this.baseReconnectDelay;
|
||||
this.lastPongTime = Date.now();
|
||||
this._safeEmit({ type: "system", content: "Connected to live server" });
|
||||
this._safeEmit({ type: "system", content: "已连接实时数据服务" });
|
||||
console.log("WebSocket connected");
|
||||
this._startHeartbeat();
|
||||
};
|
||||
@@ -79,7 +79,7 @@ export class ReadOnlyClient {
|
||||
};
|
||||
|
||||
this.ws.onclose = (event) => {
|
||||
const code = event.code || "Unknown";
|
||||
const code = event.code || "未知";
|
||||
console.log(`[WebSocket] Connection closed: Code=${code}, WasClean=${event.wasClean}`);
|
||||
|
||||
this._stopHeartbeat();
|
||||
@@ -96,7 +96,7 @@ export class ReadOnlyClient {
|
||||
|
||||
this._safeEmit({
|
||||
type: "system",
|
||||
content: "Try to connect to data server..."
|
||||
content: "正在尝试连接数据服务..."
|
||||
});
|
||||
|
||||
if (this.reconnectTimer) {
|
||||
@@ -189,4 +189,3 @@ export class ReadOnlyClient {
|
||||
this.ws = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ export function getModelIcon(modelName, modelProvider) {
|
||||
logoPath: null,
|
||||
color: "#666666",
|
||||
bgColor: "#f5f5f5",
|
||||
label: "Default",
|
||||
provider: "Default"
|
||||
label: "默认",
|
||||
provider: "默认"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ export function getModelIcon(modelName, modelProvider) {
|
||||
color: "#666666",
|
||||
bgColor: "#f5f5f5",
|
||||
label: modelName.substring(0, 15),
|
||||
provider: provider || "Unknown"
|
||||
provider: provider || "未知"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ export function getModelIcon(modelName, modelProvider) {
|
||||
*/
|
||||
export function getShortModelName(modelName) {
|
||||
if (!modelName) {
|
||||
return "N/A";
|
||||
return "暂无";
|
||||
}
|
||||
|
||||
const name = modelName.toLowerCase();
|
||||
@@ -393,4 +393,3 @@ export function getShortModelName(modelName) {
|
||||
// Return formatted original name
|
||||
return capitalizeWords(modelName);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user