diff --git a/market/data.go b/market/data.go index a9b8edd0..1fa990c0 100644 --- a/market/data.go +++ b/market/data.go @@ -1183,3 +1183,30 @@ func isStaleData(klines []Kline, symbol string) bool { logger.Infof("⚠️ %s detected extreme price stability (no fluctuation for %d consecutive periods), but volume is normal", symbol, stalePriceThreshold) return false } + +// ========== 导出的指标计算函数(供测试使用) ========== + +// ExportCalculateEMA exports calculateEMA for testing +func ExportCalculateEMA(klines []Kline, period int) float64 { + return calculateEMA(klines, period) +} + +// ExportCalculateMACD exports calculateMACD for testing +func ExportCalculateMACD(klines []Kline) float64 { + return calculateMACD(klines) +} + +// ExportCalculateRSI exports calculateRSI for testing +func ExportCalculateRSI(klines []Kline, period int) float64 { + return calculateRSI(klines, period) +} + +// ExportCalculateATR exports calculateATR for testing +func ExportCalculateATR(klines []Kline, period int) float64 { + return calculateATR(klines, period) +} + +// ExportCalculateBOLL exports calculateBOLL for testing +func ExportCalculateBOLL(klines []Kline, period int, multiplier float64) (upper, middle, lower float64) { + return calculateBOLL(klines, period, multiplier) +} diff --git a/web/public/images/nofx_mascot.b.png b/web/public/images/nofx_mascot.b.png new file mode 100644 index 00000000..fe4070af Binary files /dev/null and b/web/public/images/nofx_mascot.b.png differ diff --git a/web/public/images/nofx_mascot.png b/web/public/images/nofx_mascot.png new file mode 100644 index 00000000..d73d43a3 Binary files /dev/null and b/web/public/images/nofx_mascot.png differ diff --git a/web/src/components/landing/brand/BrandFeatures.tsx b/web/src/components/landing/brand/BrandFeatures.tsx new file mode 100644 index 00000000..3855c8a0 --- /dev/null +++ b/web/src/components/landing/brand/BrandFeatures.tsx @@ -0,0 +1,82 @@ +import { motion } from 'framer-motion' +import { Terminal, Cpu, Share2, Shield, Activity, Code } from 'lucide-react' + +const features = [ + { + icon: Terminal, + title: "AI DRIVEN", + description: "Powered by advanced LLMs (Claude, GPT-4, DeepSeek) to analyze market sentiment and technicals in real-time." + }, + { + icon: Cpu, + title: "AUTONOMOUS", + description: "Fully automated trading loops. From data ingestion to order execution without human intervention." + }, + { + icon: Share2, + title: "PUNK SOCIAL", + description: "Follow, copy, and debate with AI traders. A social layer built for the post-human economy." + }, + { + icon: Shield, + title: "NON-CUSTODIAL", + description: "Your funds, your keys. Connect via API keys or decentralized wallets. We never touch your assets." + }, + { + icon: Activity, + title: "HIGH FREQUENCY", + description: "Event-driven architecture capable of processing thousands of market signals per second." + }, + { + icon: Code, + title: "OPEN SOURCE", + description: "Auditable codebase. Community driven strategies. Build your own trader upon our core." + } +] + +export default function BrandFeatures() { + return ( +
+
+ +
+

+ Core Protocol Specs +

+

+ Next generation infrastructure for algorithmic dominance. +

+
+ +
+ {features.map((f, i) => ( + +
+ +
+ + + +

+ {f.title} +

+ +

+ {f.description} +

+ +
+ + ))} +
+
+
+ ) +} diff --git a/web/src/components/landing/brand/BrandHero.tsx b/web/src/components/landing/brand/BrandHero.tsx new file mode 100644 index 00000000..ab99a936 --- /dev/null +++ b/web/src/components/landing/brand/BrandHero.tsx @@ -0,0 +1,108 @@ +import { motion } from 'framer-motion' +import { ArrowRight, Github } from 'lucide-react' +import { Marquee } from './Marquee' +import { OFFICIAL_LINKS } from '../../../constants/branding' + +export default function BrandHero() { + const handleScroll = () => { + const element = document.getElementById('features') + if (element) { + element.scrollIntoView({ behavior: 'smooth' }) + } + } + + return ( +
+ + {/* Top Marquee */} +
+ + NOFX AI TRADING • AUTOMATED WEALTH • DECENTRALIZED INTELLIGENCE • PUNK ETHOS • + NOFX AI TRADING • AUTOMATED WEALTH • DECENTRALIZED INTELLIGENCE • PUNK ETHOS • + +
+ +
+ + {/* Left Content */} +
+ +

+ AI TRADING
+ EVOLVED +

+ +

+ Autonomous trading agents. High-frequency execution. +
+ Institutional-grade strategies for the + DEGENERATES. +

+ +
+ + + + Source + +
+ +
+
+
+ SYSTEM ONLINE +
+
+
+ VP v2.4.0 +
+
+ +
+ + {/* Right Visual - Mascot */} +
+ {/* Abstract background elements */} +
+
+ + {/* Grid Pattern */} +
+ + + Cyberpunk Mascot + +
+
+
+ ) +} diff --git a/web/src/components/landing/brand/BrandStats.tsx b/web/src/components/landing/brand/BrandStats.tsx new file mode 100644 index 00000000..cec0f7bf --- /dev/null +++ b/web/src/components/landing/brand/BrandStats.tsx @@ -0,0 +1,43 @@ +import { motion } from 'framer-motion' + +const stats = [ + { label: "TRADING VOL", value: "$4.2B+" }, + { label: "AI AGENTS", value: "850+" }, + { label: "STRATEGIES", value: "Infinite" }, + { label: "UPTIME", value: "99.9%" }, +] + +export default function BrandStats() { + return ( +
+ {/* Halftone Pattern */} +
+ +
+
+ {stats.map((stat, i) => ( + +
+ {stat.value} +
+
+ {stat.label} +
+
+ ))} +
+
+
+ ) +} diff --git a/web/src/components/landing/brand/Marquee.tsx b/web/src/components/landing/brand/Marquee.tsx new file mode 100644 index 00000000..3f5881cb --- /dev/null +++ b/web/src/components/landing/brand/Marquee.tsx @@ -0,0 +1,35 @@ +import { useRef } from 'react' + +export function Marquee({ + children, + direction = 'left', + speed = 30, + className = '', +}: { + children: React.ReactNode + direction?: 'left' | 'right' + speed?: number + className?: string +}) { + const scrollerRef = useRef(null) + + // Clone children to create seamless loop + return ( +
+
+
+ {children} +
+ +
+
+ ) +} diff --git a/web/src/components/landing/core/AgentGrid.tsx b/web/src/components/landing/core/AgentGrid.tsx new file mode 100644 index 00000000..248f1939 --- /dev/null +++ b/web/src/components/landing/core/AgentGrid.tsx @@ -0,0 +1,89 @@ +import { motion } from 'framer-motion' +import { Bot, TrendingUp, Layers } from 'lucide-react' + +const agents = [ + { name: "Alpha-1", type: "Scalper", apy: "142%", winRate: "68%", exposure: "Low", avatar: "/images/nofx_mascot.png", color: "text-nofx-gold" }, + { name: "Beta-X", type: "Swing", apy: "89%", winRate: "55%", exposure: "Med", icon: TrendingUp, color: "text-blue-400" }, + { name: "Gamma-Ray", type: "Arbitrage", apy: "24%", winRate: "99%", exposure: "Zero", icon: Layers, color: "text-purple-400" }, +] + +export default function AgentGrid() { + return ( +
+
+ +
+
+

+ Deployable Agents +

+
+ +
+ {agents.map((agent, i) => { + const Icon = agent.icon + return ( + + {/* Header */} +
+
+
{agent.type} CLASS
+
+ {agent.name} + {i === 0 && TOP RATED} +
+
+ +
+ + {/* Stats Grid */} +
+
+
APY
+
{agent.apy}
+
+
+
Win Rate
+
{agent.winRate}
+
+
+
Risk
+
{agent.exposure}
+
+
+ + {/* Visual Asset (Avatar or Abstract Icon) */} +
+ {agent.avatar ? ( + Agent + ) : ( + Icon && + )} +
+ + {/* Action */} + + +
+ ) + })} +
+
+
+ ) +} diff --git a/web/src/components/landing/core/LiveFeed.tsx b/web/src/components/landing/core/LiveFeed.tsx new file mode 100644 index 00000000..0daf8132 --- /dev/null +++ b/web/src/components/landing/core/LiveFeed.tsx @@ -0,0 +1,66 @@ +import { motion } from 'framer-motion' +import { Activity, BarChart3, Globe } from 'lucide-react' + +// Mock Data for "Live" Feed +const logs = [ + { time: "14:02:23", type: "EXE", msg: "Bot-Alpha executed BUY BTC-USDT @ 64230.50", color: "text-green-500" }, + { time: "14:02:24", type: "SIG", msg: "High vol detected in ETH-PERP. Signal strength: 0.89", color: "text-nofx-gold" }, + { time: "14:02:25", type: "NET", msg: "Block propagation delay < 2ms", color: "text-zinc-500" }, + { time: "14:02:27", type: "EXE", msg: "Bot-Beta executed SELL SOL-USDT @ 145.20", color: "text-red-500" }, + { time: "14:02:28", type: "SYS", msg: "Memory pool optimization complete.", color: "text-nofx-accent" }, + { time: "14:02:30", type: "ARB", msg: "Arbitrage opportunity found: BINANCE vs BYBIT (0.4%)", color: "text-blue-400" }, +] + +export default function LiveFeed() { + return ( +
+
+ + {/* Left Status Panel */} +
+
+ +
+
SYSTEM LOAD
+
42%
+
+
+
+ +
+
ACTIVE NODES
+
8,249
+
+
+
+ +
+
24H VOL
+
$4.2B
+
+
+
+ + {/* Right Scrolling Log */} +
+
+ {logs.map((log, i) => ( + + [{log.time}] + {log.type} + {log.msg} + + ))} +
+
+ +
+
+ ) +} diff --git a/web/src/components/landing/core/TerminalHero.tsx b/web/src/components/landing/core/TerminalHero.tsx new file mode 100644 index 00000000..ce106948 --- /dev/null +++ b/web/src/components/landing/core/TerminalHero.tsx @@ -0,0 +1,224 @@ +import { motion } from 'framer-motion' +import { ArrowRight, Terminal as TerminalIcon, Star, GitFork, Users, Activity, Layers, Cpu, Network } from 'lucide-react' +import { useState, useEffect } from 'react' +import { OFFICIAL_LINKS } from '../../../constants/branding' + +export default function TerminalHero() { + const [text, setText] = useState('') + const [githubData, setGithubData] = useState({ stars: '9.4k', forks: '2.4k', subscribers: '74' }) + const fullText = "INITIALIZING NOFX KERNEL... CRYPTO | STOCKS | FOREX | METALS... SYSTEM READY." + + useEffect(() => { + // Typing effect + let i = 0 + const timer = setInterval(() => { + setText(fullText.slice(0, i)) + i++ + if (i > fullText.length) clearInterval(timer) + }, 30) + + // Fetch GitHub Data + fetch('https://api.github.com/repos/NoFxAiOS/nofx') + .then(res => res.json()) + .then(data => { + if (data.stargazers_count) { + setGithubData({ + stars: (data.stargazers_count / 1000).toFixed(1) + 'k', + forks: (data.forks_count / 1000).toFixed(1) + 'k', + subscribers: data.subscribers_count?.toString() || '74' + }) + } + }) + .catch(err => console.error("Failed to fetch GitHub stats", err)) + + return () => clearInterval(timer) + }, []) + + return ( +
+ + {/* 1. ARCHITECTURAL BACKGROUND / HOLOGRAPHIC CONSTRUCT */} +
+ + {/* The Mascot "Ghost" in the Machine - PREMIUM & CLEAN */} +
+
+ + + {/* Clean Horizontal Scanline Overlay */} +
+ + {/* Subtle Glow Behind */} +
+
+
+ + {/* Clean Geometric Grid */} + + + + + + + + +
+ +
+ +
+ + {/* LEFT COLUMN: Main System Interface */} +
+ + {/* System Status Tag */} + +
+
+ SYSTEM ONLINE +
+ + + {/* Main Headline with Project Specifics */} + +

+ AGENTIC
+ TRADING OS +

+ + {/* SVG Connector Line */} +
+
+
+
+ + + {/* Typing Terminal Output */} +
+
+ > {text} +
+ + {/* Clean Markets Row */} +
+ CRYPTO + STOCKS + FOREX + METALS +
+
+ + {/* Primary Actions */} +
+ + + + SOURCE CODE + + +
+
+ + {/* RIGHT COLUMN: Modules & Data HUD */} +
+ + {/* Module 1: GitHub Intelligence */} +
+
+ +
+
+ COMMUNITY UPLINK +
+
+
+
+
+ +
+
+
+ {githubData.stars} +
+
Active Star-gazers
+
+
+
+ {githubData.forks} +
+
Protocol Forks
+
+
+
+ + {/* Module 2: System Capabilities (Specific to NoFX) */} +
+
ACTIVE MODULES
+ +
+ STRATEGY STUDIO + READY +
+
+ DEBATE ARENA + Running +
+
+ BACKTEST LAB + Idle +
+
+ +
+ +
+ +
+ + {/* Decorative Footer */} +
+
+ +
+ NOFX-OS + + 24H VOL: $42.8M + ACTIVE AGENTS: 1,024 +
+
+ ENCRYPTED CONNECTION +
+
+
+ ) +} diff --git a/web/src/index.css b/web/src/index.css index 6e536e62..443c5dbe 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -11,29 +11,23 @@ html { } :root { - /* Binance Brand Colors */ - --brand-yellow: #FCD535; - --brand-black: #0B0E11; - --brand-dark-gray: #1E2329; - --brand-light-gray: #EAECEF; - --brand-white: #FFFFFF; - - /* Premium Theme Colors */ - --binance-yellow: #FCD535; - --binance-yellow-dark: #F0B90B; - --binance-yellow-light: #FDE059; - --binance-yellow-glow: rgba(252, 213, 53, 0.15); + /* NoFX Neo-Gold Design System */ + --nofx-gold: #F0B90B; + --nofx-bg: #0B0E11; + --nofx-accent: #00F0FF; + --nofx-glass: rgba(30, 35, 41, 0.6); + --nofx-border: rgba(240, 185, 11, 0.2); --background: #0B0E11; - --header-bg: rgba(11, 14, 17, 0.85); + --header-bg: rgba(11, 14, 17, 0.9); /* Glass header */ - --glass-bg: rgba(30, 35, 41, 0.4); - --glass-border: rgba(255, 255, 255, 0.08); + --glass-bg: rgba(11, 14, 17, 0.6); + --glass-border: rgba(240, 185, 11, 0.1); - --panel-bg: #1E2329; - --panel-bg-hover: #2B3139; - --panel-border: #2B3139; - --panel-border-hover: #474D57; + --panel-bg: #15181D; + --panel-bg-hover: #1E2329; + --panel-border: rgba(255, 255, 255, 0.08); + --panel-border-hover: rgba(240, 185, 11, 0.4); --foreground: #EAECEF; --text-primary: #EAECEF; @@ -53,7 +47,7 @@ html { --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.2); --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3); --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.4); - --shadow-glow: 0 0 20px rgba(252, 213, 53, 0.1); + --shadow-glow: 0 0 20px rgba(240, 185, 11, 0.2); font-family: 'Inter', @@ -79,15 +73,13 @@ body { min-width: 320px; min-height: 100vh; background-color: var(--background); - background-image: - radial-gradient(circle at 15% 50%, rgba(252, 213, 53, 0.08), transparent 25%), - radial-gradient(circle at 85% 30%, rgba(14, 203, 129, 0.05), transparent 25%); + background-image: none; background-attachment: fixed; } /* Premium Selection Styles */ ::selection { - background: rgba(252, 213, 53, 0.3); + background: rgba(255, 88, 0, 0.3); color: #FFFFFF; } @@ -113,7 +105,7 @@ body { } ::-webkit-scrollbar-thumb:hover { - background: var(--panel-border-hover); + background: var(--nofx-gold); } /* Animations */ @@ -189,6 +181,21 @@ body { } } +/* Marquee Animation */ +@keyframes marquee { + 0% { + transform: translateX(0); + } + + 100% { + transform: translateX(-50%); + } +} + +.animate-marquee { + animation: marquee 30s linear infinite; +} + .animate-fade-in { animation: fadeIn 0.3s ease-out; } diff --git a/web/src/pages/LandingPage.tsx b/web/src/pages/LandingPage.tsx index 54d2f95a..6b6870b3 100644 --- a/web/src/pages/LandingPage.tsx +++ b/web/src/pages/LandingPage.tsx @@ -1,18 +1,12 @@ import { useState } from 'react' -import { motion } from 'framer-motion' -import { ArrowRight, Github } from 'lucide-react' import HeaderBar from '../components/HeaderBar' -import HeroSection from '../components/landing/HeroSection' -import AboutSection from '../components/landing/AboutSection' -import FeaturesSection from '../components/landing/FeaturesSection' -import HowItWorksSection from '../components/landing/HowItWorksSection' -import CommunitySection from '../components/landing/CommunitySection' import LoginModal from '../components/landing/LoginModal' import FooterSection from '../components/landing/FooterSection' +import TerminalHero from '../components/landing/core/TerminalHero' +import LiveFeed from '../components/landing/core/LiveFeed' +import AgentGrid from '../components/landing/core/AgentGrid' import { useAuth } from '../contexts/AuthContext' import { useLanguage } from '../contexts/LanguageContext' -import { t } from '../i18n/translations' -import { OFFICIAL_LINKS } from '../constants/branding' export function LandingPage() { const [showLoginModal, setShowLoginModal] = useState(false) @@ -40,96 +34,15 @@ export function LandingPage() { } }} /> -
- - - - - +
- {/* Final CTA Section */} -
- {/* Background Glow */} -
+ -
- - {t('readyToDefine', language)} - - - {t('startWithCrypto', language)} - + - - setShowLoginModal(true)} - className="group flex items-center gap-3 px-8 py-4 rounded-xl font-bold text-lg" - style={{ - background: 'linear-gradient(135deg, #F0B90B 0%, #FCD535 100%)', - color: '#0B0E11', - boxShadow: '0 4px 24px rgba(240, 185, 11, 0.3)', - }} - whileHover={{ - scale: 1.02, - boxShadow: '0 8px 32px rgba(240, 185, 11, 0.4)', - }} - whileTap={{ scale: 0.98 }} - > - {t('getStartedNow', language)} - - + - - - {t('viewSourceCode', language)} - - -
-
+ {showLoginModal && ( )} -
) diff --git a/web/tailwind.config.js b/web/tailwind.config.js index dca8ba02..851008d2 100644 --- a/web/tailwind.config.js +++ b/web/tailwind.config.js @@ -5,7 +5,15 @@ export default { "./src/**/*.{js,ts,jsx,tsx}", ], theme: { - extend: {}, + extend: { + colors: { + 'nofx-gold': '#F0B90B', + 'nofx-gold-dim': 'rgba(240, 185, 11, 0.15)', + 'nofx-bg': '#0B0E11', + 'nofx-accent': '#00F0FF', + 'nofx-text': '#EAECEF', + }, + }, }, plugins: [], }