├── .gitignore
├── LICENSE
├── README.md
├── README_CN.md
├── assets
└── logo.svg
├── contracts
├── FollowTrade.sol
├── MemeInteraction.sol
├── SocialInteraction.sol
└── TokenGovernance.sol
├── docs
├── API.md
└── DEVELOPER.md
├── package-lock.json
├── package.json
├── program
└── src
│ ├── follow_trade.rs
│ └── lib.rs
└── src
├── ai_engine
├── market_data.py
├── meme_generator.py
├── ml_models.py
├── risk_manager.py
├── signal_generator.py
├── trading_engine.py
└── voice_generator.py
├── config
└── ai_social_config.js
├── contracts
└── abi.js
├── index.js
└── services
├── follow_trade_service.js
├── real_time_processor.js
├── real_time_service.js
├── social_media_service.js
└── trading_service.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | node_modules/
3 | .env
4 |
5 | # Build outputs
6 | dist/
7 | build/
8 |
9 | # IDE and editor files
10 | .idea/
11 | .vscode/
12 | *.swp
13 | *.swo
14 |
15 | # Logs
16 | logs/
17 | *.log
18 | npm-debug.log*
19 |
20 | # Testing
21 | coverage/
22 |
23 | # Python
24 | __pycache__/
25 | *.py[cod]
26 | *.so
27 |
28 | # Solidity
29 | artifacts/
30 | cache/
31 |
32 | # Misc
33 | .DS_Store
34 | Thumbs.db
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 DeepRug
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # DeepRug (RUG) Project
6 |
7 | [中文文档](README_CN.md) | [License](LICENSE)
8 |
9 | > Let AI tear open the quantitative black box - either get rich or Rug Pull yourself!
10 |
11 | ## 🚀 Project Overview
12 |
13 | DeepRug is a revolutionary AI quantitative trading platform that perfectly combines AI trading strategies with social entertainment. Through 100% on-chain live trading operations, it provides users with a transparent and highly entertaining trading experience.
14 |
15 | ## 🌟 Core Features
16 |
17 | ### 1. Transparent Quantitative Casino
18 | - Real-time ETH/BTC trading based on DeepSeek engine
19 | - Real-time trading signals published on-chain
20 | - Profit/loss live streaming
21 | - User 1-second delay copy trading system
22 |
23 | ### 2. AI Strategy Open Source Challenge
24 | - Weekly release of simplified strategy code
25 | - Community strategy optimization reward mechanism
26 | - Fun code comment culture
27 |
28 | ### 3. AI vs Human Trading Competition
29 | - Monthly "Retail vs AI" competition
30 | - AI real-time commentary system
31 | - Live interactive experience
32 |
33 | ### 4. RUG Token Economics
34 | - Copy trading fee token discount
35 | - Governance voting rights
36 | - Strategy data access rights
37 | - Deflationary burn mechanism (0-50% burn rate)
38 |
39 | ## 🔥 Community Features
40 | - AI Trading Live Stream
41 | - Rug Pull Badge System
42 | - AI Confession Simulator
43 | - Comparative Analysis Weekly Report
44 |
45 | ## 📚 Technical Architecture
46 |
47 | ### Smart Contract System
48 | - FollowTrade Contract: Manages copy trading and profit distribution
49 | - Follow trade management with fee system
50 | - Profit distribution (70% trader / 30% follower)
51 | - Token burn mechanism (0-50% rate)
52 | - Reward withdrawal system
53 | - MemeInteraction Contract: Handles social engagement
54 | - TokenGovernance Contract: Manages platform governance
55 | - SocialInteraction Contract: Manages community features
56 |
57 | ### AI Engine (Python)
58 | - Market data analysis (market_data.py)
59 | - Trading signal generation (signal_generator.py)
60 | - Risk management system (risk_manager.py)
61 | - ML model implementation (ml_models.py)
62 | - Trading execution engine (trading_engine.py)
63 | - Meme and voice content generation
64 |
65 | ### Backend Services (Node.js)
66 | - Real-time data processing service
67 | - WebSocket server (ws://localhost:8081)
68 | - Trading service integration
69 | - Social media integration
70 | - Follow trade service
71 |
72 | ### Frontend Application
73 | - Web Interface (React)
74 | - Real-time Data Visualization
75 | - Social Interaction Features
76 |
77 | ### Blockchain Integration
78 | - On-chain Data Storage
79 | - Smart Contract Interaction
80 | - Token Economic System
81 |
82 | ### Data System
83 | - Market Data Collection
84 | - Trading Signal Analysis
85 | - User Behavior Analysis
86 |
87 | ## 🚀 Development Roadmap
88 |
89 | ### Phase One: Infrastructure (In Progress)
90 | - [ ] Build AI Trading Engine
91 | - [x] Develop Smart Contracts
92 | - [ ] Build Data Processing System
93 |
94 | ### Phase Two: Core Features
95 | - [ ] Implement Live Trading Stream
96 | - [ ] Develop Copy Trading System
97 | - [ ] Deploy Token Contract
98 |
99 | ### Phase Three: Community Features
100 | - [ ] Implement Social Interaction Features
101 | - [ ] Develop NFT Badge System
102 | - [ ] Build Data Analysis Platform
103 |
104 | ## ⚠️ Project Status
105 |
106 | This project is currently under active development. The core smart contracts and basic infrastructure are implemented, but many features are still being developed and refined. We welcome community contributions to help accelerate development.
107 |
108 | ## 📝 Contribution Guidelines
109 |
110 | Welcome to join DeepRug development! Please check our contribution guidelines to learn how to participate in project development.
111 |
112 | ## 📄 License
113 |
114 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
--------------------------------------------------------------------------------
/README_CN.md:
--------------------------------------------------------------------------------
1 | # DeepRug (RUG) 项目
2 |
3 | > 让 AI 撕开量化交易的黑盒 - 要么暴富,要么被 Rug Pull!
4 |
5 | ## 🚀 项目概述
6 |
7 | DeepRug 是一个革命性的 AI 量化交易平台,完美地将 AI 交易策略与社交娱乐相结合。通过100%链上实时交易操作,为用户提供透明且高度娱乐性的交易体验。
8 |
9 | ## 🌟 核心功能
10 |
11 | ### 1. 透明量化赌场
12 | - 基于 DeepSeek 引擎的实时 ETH/BTC 交易
13 | - 链上实时发布交易信号
14 | - 实时盈亏直播
15 | - 用户1秒延迟跟单系统
16 |
17 | ### 2. AI 策略开源挑战
18 | - 每周发布简化策略代码
19 | - 社区策略优化奖励机制
20 | - 趣味代码注释文化
21 |
22 | ### 3. AI vs 人类交易大赛
23 | - 每月"散户大战 AI"比赛
24 | - AI 实时解说系统
25 | - 现场互动体验
26 |
27 | ### 4. RUG 代币经济
28 | - 跟单费用代币折扣
29 | - 治理投票权
30 | - 策略数据访问权
31 | - 通缩销毁机制(0-50%销毁率)
32 |
33 | ## 🔥 社区特色
34 | - AI 交易直播
35 | - Rug Pull 徽章系统
36 | - AI 忏悔模拟器
37 | - 每周对比分析报告
38 |
39 | ## 📚 技术架构
40 |
41 | ### 智能合约系统
42 | - 跟单交易合约:管理跟单交易和利润分配
43 | - 跟单管理及费用系统
44 | - 利润分配(交易者70% / 跟单者30%)
45 | - 代币销毁机制(0-50%销毁率)
46 | - 奖励提取系统
47 | - 表情包互动合约:处理社交互动
48 | - 代币治理合约:管理平台治理
49 | - 社交互动合约:管理社区功能
50 |
51 | ### AI 引擎(Python)
52 | - 市场数据分析(market_data.py)
53 | - 交易信号生成(signal_generator.py)
54 | - 风险管理系统(risk_manager.py)
55 | - 机器学习模型实现(ml_models.py)
56 | - 交易执行引擎(trading_engine.py)
57 | - 表情包和语音内容生成
58 |
59 | ### 后端服务(Node.js)
60 | - 实时数据处理服务
61 | - WebSocket 服务器(ws://localhost:8081)
62 | - 交易服务集成
63 | - 社交媒体集成
64 | - 跟单交易服务
65 |
66 | ### 前端应用
67 | - Web 界面(React)
68 | - 实时数据可视化
69 | - 社交互动功能
70 |
71 | ### 区块链集成
72 | - 链上数据存储
73 | - 智能合约交互
74 | - 代币经济系统
75 |
76 | ### 数据系统
77 | - 市场数据采集
78 | - 交易信号分析
79 | - 用户行为分析
80 |
81 | ## 🚀 开发路线图
82 |
83 | ### 第一阶段:基础设施(进行中)
84 | - [ ] 构建 AI 交易引擎
85 | - [x] 开发智能合约
86 | - [ ] 构建数据处理系统
87 |
88 | ### 第二阶段:核心功能
89 | - [ ] 实现实时交易直播
90 | - [ ] 开发跟单系统
91 | - [ ] 部署代币合约
92 |
93 | ### 第三阶段:社区功能
94 | - [ ] 实现社交互动功能
95 | - [ ] 开发 NFT 徽章系统
96 | - [ ] 构建数据分析平台
97 |
98 | ## ⚠️ 项目状态
99 |
100 | 本项目目前正在积极开发中。核心智能合约和基础设施已经实现,但许多功能仍在开发和完善中。我们欢迎社区贡献,帮助加速开发进程。
101 |
102 | ## 📝 贡献指南
103 |
104 | 欢迎加入 DeepRug 开发!请查看我们的贡献指南,了解如何参与项目开发。
105 |
106 | ## 📄 许可证
107 |
108 | 本项目采用 MIT 许可证。详情请参阅 [LICENSE](LICENSE) 文件。
--------------------------------------------------------------------------------
/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
37 |
--------------------------------------------------------------------------------
/contracts/FollowTrade.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 |
4 | contract FollowTrade {
5 | // State variables
6 | address public owner;
7 | uint256 public followFee;
8 | uint256 public burnRate;
9 | uint256 public totalBurned;
10 | mapping(address => uint256) public balances;
11 | mapping(address => mapping(string => bool)) public activeFollows;
12 | mapping(address => uint256) public traderRewards;
13 |
14 | // Events
15 | event FollowTradeStarted(address follower, string symbol, uint256 fee);
16 | event ProfitDistributed(address trader, address follower, uint256 amount);
17 | event TokensBurned(uint256 amount);
18 | event RewardsWithdrawn(address user, uint256 amount);
19 |
20 | constructor(uint256 _followFee, uint256 _burnRate) {
21 | require(_burnRate <= 50, "Burn rate cannot exceed 50%");
22 | owner = msg.sender;
23 | followFee = _followFee;
24 | burnRate = _burnRate;
25 | }
26 |
27 | // Modifiers
28 | modifier onlyOwner() {
29 | require(msg.sender == owner, "Only owner can call this function");
30 | _;
31 | }
32 |
33 | modifier onlyActiveFollower(string memory symbol) {
34 | require(activeFollows[msg.sender][symbol], "Not an active follower");
35 | _;
36 | }
37 |
38 | // Follow trade function
39 | function startFollow(string memory symbol) external payable {
40 | require(msg.value >= followFee, "Insufficient follow fee");
41 | require(!activeFollows[msg.sender][symbol], "Already following this symbol");
42 |
43 | // Calculate burn amount
44 | uint256 burnAmount = (followFee * burnRate) / 100;
45 | uint256 systemAmount = followFee - burnAmount;
46 |
47 | // Update state
48 | activeFollows[msg.sender][symbol] = true;
49 | balances[owner] += systemAmount;
50 | totalBurned += burnAmount;
51 |
52 | // Burn tokens
53 | address deadAddress = address(0);
54 | payable(deadAddress).transfer(burnAmount);
55 |
56 | // Refund excess payment
57 | if (msg.value > followFee) {
58 | payable(msg.sender).transfer(msg.value - followFee);
59 | }
60 |
61 | emit FollowTradeStarted(msg.sender, symbol, followFee);
62 | emit TokensBurned(burnAmount);
63 | }
64 |
65 | // Distribute profits
66 | function distributeProfits(address[] calldata followers, uint256[] calldata amounts) external onlyOwner {
67 | require(followers.length == amounts.length, "Arrays length mismatch");
68 |
69 | for (uint256 i = 0; i < followers.length; i++) {
70 | address follower = followers[i];
71 | uint256 amount = amounts[i];
72 |
73 | require(balances[owner] >= amount, "Insufficient balance");
74 |
75 | // Calculate profit shares
76 | uint256 traderShare = (amount * 70) / 100; // 70% to trader
77 | uint256 followerShare = amount - traderShare; // 30% to follower
78 |
79 | // Update balances
80 | balances[owner] -= amount;
81 | balances[follower] += followerShare;
82 | traderRewards[msg.sender] += traderShare;
83 |
84 | emit ProfitDistributed(msg.sender, follower, amount);
85 | }
86 | }
87 |
88 | // Withdraw rewards
89 | function withdrawRewards() external {
90 | uint256 amount = traderRewards[msg.sender];
91 | require(amount > 0, "No rewards to withdraw");
92 |
93 | traderRewards[msg.sender] = 0;
94 | payable(msg.sender).transfer(amount);
95 |
96 | emit RewardsWithdrawn(msg.sender, amount);
97 | }
98 |
99 | // Withdraw balance
100 | function withdraw() external {
101 | uint256 amount = balances[msg.sender];
102 | require(amount > 0, "No balance to withdraw");
103 |
104 | balances[msg.sender] = 0;
105 | payable(msg.sender).transfer(amount);
106 | }
107 |
108 | // Update parameters
109 | function updateFollowFee(uint256 _newFee) external onlyOwner {
110 | followFee = _newFee;
111 | }
112 |
113 | function updateBurnRate(uint256 _newRate) external onlyOwner {
114 | require(_newRate <= 50, "Burn rate cannot exceed 50%");
115 | burnRate = _newRate;
116 | }
117 |
118 | // View functions
119 | function getFollowerStatus(address follower, string memory symbol) external view returns (bool) {
120 | return activeFollows[follower][symbol];
121 | }
122 |
123 | function getTraderRewards(address trader) external view returns (uint256) {
124 | return traderRewards[trader];
125 | }
126 | }
--------------------------------------------------------------------------------
/contracts/MemeInteraction.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 |
4 | contract MemeInteraction {
5 | // State variables
6 | address public owner;
7 | uint256 public memeCount;
8 | uint256 public minimumStakeAmount;
9 |
10 | struct Meme {
11 | address creator;
12 | string content;
13 | string imageHash;
14 | uint256 timestamp;
15 | uint256 likes;
16 | uint256 shares;
17 | mapping(address => bool) hasLiked;
18 | mapping(address => bool) hasShared;
19 | }
20 |
21 | mapping(uint256 => Meme) public memes;
22 | mapping(address => uint256[]) public userMemes;
23 | mapping(address => uint256) public userReputation;
24 |
25 | // Events
26 | event MemeCreated(uint256 indexed memeId, address indexed creator, string content, string imageHash);
27 | event MemeLiked(uint256 indexed memeId, address indexed liker);
28 | event MemeShared(uint256 indexed memeId, address indexed sharer);
29 | event ReputationUpdated(address indexed user, uint256 newReputation);
30 |
31 | constructor(uint256 _minimumStakeAmount) {
32 | owner = msg.sender;
33 | minimumStakeAmount = _minimumStakeAmount;
34 | memeCount = 0;
35 | }
36 |
37 | modifier onlyOwner() {
38 | require(msg.sender == owner, "Only owner can call this function");
39 | _;
40 | }
41 |
42 | // Meme Creation and Interaction Functions
43 | function createMeme(string memory content, string memory imageHash) external {
44 | memeCount++;
45 | Meme storage meme = memes[memeCount];
46 | meme.creator = msg.sender;
47 | meme.content = content;
48 | meme.imageHash = imageHash;
49 | meme.timestamp = block.timestamp;
50 | meme.likes = 0;
51 | meme.shares = 0;
52 |
53 | userMemes[msg.sender].push(memeCount);
54 | userReputation[msg.sender] += 1;
55 |
56 | emit MemeCreated(memeCount, msg.sender, content, imageHash);
57 | emit ReputationUpdated(msg.sender, userReputation[msg.sender]);
58 | }
59 |
60 | function likeMeme(uint256 memeId) external {
61 | Meme storage meme = memes[memeId];
62 | require(!meme.hasLiked[msg.sender], "Already liked this meme");
63 |
64 | meme.likes++;
65 | meme.hasLiked[msg.sender] = true;
66 | userReputation[meme.creator] += 1;
67 |
68 | emit MemeLiked(memeId, msg.sender);
69 | emit ReputationUpdated(meme.creator, userReputation[meme.creator]);
70 | }
71 |
72 | function shareMeme(uint256 memeId) external {
73 | Meme storage meme = memes[memeId];
74 | require(!meme.hasShared[msg.sender], "Already shared this meme");
75 |
76 | meme.shares++;
77 | meme.hasShared[msg.sender] = true;
78 | userReputation[meme.creator] += 2;
79 | userReputation[msg.sender] += 1;
80 |
81 | emit MemeShared(memeId, msg.sender);
82 | emit ReputationUpdated(meme.creator, userReputation[meme.creator]);
83 | emit ReputationUpdated(msg.sender, userReputation[msg.sender]);
84 | }
85 |
86 | // Reputation Management Functions
87 | function getReputation(address user) external view returns (uint256) {
88 | return userReputation[user];
89 | }
90 |
91 | function getUserMemes(address user) external view returns (uint256[] memory) {
92 | return userMemes[user];
93 | }
94 |
95 | // Admin Functions
96 | function updateMinimumStakeAmount(uint256 _newAmount) external onlyOwner {
97 | minimumStakeAmount = _newAmount;
98 | }
99 | }
--------------------------------------------------------------------------------
/contracts/SocialInteraction.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 |
4 | contract SocialInteraction {
5 | // State variables
6 | address public owner;
7 | uint256 public tradingCompetitionId;
8 | uint256 public minimumStakeAmount;
9 |
10 | struct TradingCompetition {
11 | uint256 startTime;
12 | uint256 endTime;
13 | uint256 prizePool;
14 | mapping(address => uint256) participantScores;
15 | address[] participants;
16 | bool isActive;
17 | }
18 |
19 | struct CommunityPost {
20 | address author;
21 | string content;
22 | uint256 timestamp;
23 | uint256 likes;
24 | mapping(address => bool) hasLiked;
25 | }
26 |
27 | mapping(uint256 => TradingCompetition) public competitions;
28 | mapping(uint256 => CommunityPost) public posts;
29 | uint256 public postCount;
30 | mapping(address => uint256) public userStakes;
31 |
32 | // Events
33 | event CompetitionStarted(uint256 indexed competitionId, uint256 startTime, uint256 endTime);
34 | event CompetitionEnded(uint256 indexed competitionId, address[] winners);
35 | event PostCreated(uint256 indexed postId, address indexed author, string content);
36 | event PostLiked(uint256 indexed postId, address indexed liker);
37 | event UserStaked(address indexed user, uint256 amount);
38 |
39 | constructor(uint256 _minimumStakeAmount) {
40 | owner = msg.sender;
41 | minimumStakeAmount = _minimumStakeAmount;
42 | tradingCompetitionId = 0;
43 | postCount = 0;
44 | }
45 |
46 | modifier onlyOwner() {
47 | require(msg.sender == owner, "Only owner can call this function");
48 | _;
49 | }
50 |
51 | modifier hasStaked() {
52 | require(userStakes[msg.sender] >= minimumStakeAmount, "Must stake minimum amount");
53 | _;
54 | }
55 |
56 | // Trading Competition Functions
57 | function startCompetition(uint256 _duration) external onlyOwner {
58 | tradingCompetitionId++;
59 | uint256 startTime = block.timestamp;
60 | uint256 endTime = startTime + _duration;
61 |
62 | TradingCompetition storage competition = competitions[tradingCompetitionId];
63 | competition.startTime = startTime;
64 | competition.endTime = endTime;
65 | competition.isActive = true;
66 |
67 | emit CompetitionStarted(tradingCompetitionId, startTime, endTime);
68 | }
69 |
70 | function joinCompetition() external hasStaked {
71 | TradingCompetition storage competition = competitions[tradingCompetitionId];
72 | require(competition.isActive, "No active competition");
73 | require(block.timestamp < competition.endTime, "Competition ended");
74 |
75 | competition.participants.push(msg.sender);
76 | competition.participantScores[msg.sender] = 0;
77 | }
78 |
79 | function updateScore(address participant, uint256 score) external onlyOwner {
80 | TradingCompetition storage competition = competitions[tradingCompetitionId];
81 | require(competition.isActive, "No active competition");
82 | competition.participantScores[participant] = score;
83 | }
84 |
85 | function endCompetition() external onlyOwner {
86 | TradingCompetition storage competition = competitions[tradingCompetitionId];
87 | require(competition.isActive, "No active competition");
88 | require(block.timestamp >= competition.endTime, "Competition still ongoing");
89 |
90 | competition.isActive = false;
91 |
92 | // Calculate winners (top 3)
93 | address[] memory winners = new address[](3);
94 | uint256[] memory topScores = new uint256[](3);
95 |
96 | for (uint256 i = 0; i < competition.participants.length; i++) {
97 | address participant = competition.participants[i];
98 | uint256 score = competition.participantScores[participant];
99 |
100 | for (uint256 j = 0; j < 3; j++) {
101 | if (score > topScores[j]) {
102 | // Shift lower scores down
103 | for (uint256 k = 2; k > j; k--) {
104 | topScores[k] = topScores[k-1];
105 | winners[k] = winners[k-1];
106 | }
107 | topScores[j] = score;
108 | winners[j] = participant;
109 | break;
110 | }
111 | }
112 | }
113 |
114 | emit CompetitionEnded(tradingCompetitionId, winners);
115 | }
116 |
117 | // Community Interaction Functions
118 | function createPost(string memory content) external hasStaked {
119 | postCount++;
120 | CommunityPost storage post = posts[postCount];
121 | post.author = msg.sender;
122 | post.content = content;
123 | post.timestamp = block.timestamp;
124 | post.likes = 0;
125 |
126 | emit PostCreated(postCount, msg.sender, content);
127 | }
128 |
129 | function likePost(uint256 postId) external hasStaked {
130 | CommunityPost storage post = posts[postId];
131 | require(!post.hasLiked[msg.sender], "Already liked this post");
132 |
133 | post.likes++;
134 | post.hasLiked[msg.sender] = true;
135 |
136 | emit PostLiked(postId, msg.sender);
137 | }
138 |
139 | // Staking Functions
140 | function stake() external payable {
141 | require(msg.value > 0, "Must stake some amount");
142 | userStakes[msg.sender] += msg.value;
143 | emit UserStaked(msg.sender, msg.value);
144 | }
145 |
146 | function withdraw(uint256 amount) external {
147 | require(userStakes[msg.sender] >= amount, "Insufficient stake");
148 | userStakes[msg.sender] -= amount;
149 | payable(msg.sender).transfer(amount);
150 | }
151 | }
--------------------------------------------------------------------------------
/contracts/TokenGovernance.sol:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: MIT
2 | pragma solidity ^0.8.0;
3 |
4 | contract TokenGovernance {
5 | // State variables
6 | address public owner;
7 | uint256 public proposalCount;
8 | uint256 public minimumStakeForProposal;
9 | uint256 public votingPeriod;
10 |
11 | struct Proposal {
12 | address proposer;
13 | string description;
14 | uint256 startTime;
15 | uint256 endTime;
16 | uint256 forVotes;
17 | uint256 againstVotes;
18 | bool executed;
19 | mapping(address => bool) hasVoted;
20 | mapping(address => uint256) stakedAmount;
21 | }
22 |
23 | mapping(uint256 => Proposal) public proposals;
24 | mapping(address => uint256) public userStakes;
25 | mapping(address => uint256) public votingPower;
26 |
27 | // Events
28 | event ProposalCreated(uint256 indexed proposalId, address indexed proposer, string description);
29 | event VoteCast(uint256 indexed proposalId, address indexed voter, bool support, uint256 weight);
30 | event ProposalExecuted(uint256 indexed proposalId);
31 | event TokensStaked(address indexed user, uint256 amount);
32 | event TokensUnstaked(address indexed user, uint256 amount);
33 |
34 | constructor(uint256 _minimumStakeForProposal, uint256 _votingPeriod) {
35 | owner = msg.sender;
36 | minimumStakeForProposal = _minimumStakeForProposal;
37 | votingPeriod = _votingPeriod;
38 | proposalCount = 0;
39 | }
40 |
41 | modifier onlyOwner() {
42 | require(msg.sender == owner, "Only owner can call this function");
43 | _;
44 | }
45 |
46 | // Staking Functions
47 | function stake() external payable {
48 | require(msg.value > 0, "Must stake some amount");
49 | userStakes[msg.sender] += msg.value;
50 | votingPower[msg.sender] = calculateVotingPower(msg.sender);
51 | emit TokensStaked(msg.sender, msg.value);
52 | }
53 |
54 | function unstake(uint256 amount) external {
55 | require(userStakes[msg.sender] >= amount, "Insufficient stake");
56 | require(canUnstake(msg.sender, amount), "Tokens locked in active proposals");
57 |
58 | userStakes[msg.sender] -= amount;
59 | votingPower[msg.sender] = calculateVotingPower(msg.sender);
60 | payable(msg.sender).transfer(amount);
61 |
62 | emit TokensUnstaked(msg.sender, amount);
63 | }
64 |
65 | // Governance Functions
66 | function createProposal(string memory description) external {
67 | require(userStakes[msg.sender] >= minimumStakeForProposal, "Insufficient stake to create proposal");
68 |
69 | proposalCount++;
70 | Proposal storage proposal = proposals[proposalCount];
71 | proposal.proposer = msg.sender;
72 | proposal.description = description;
73 | proposal.startTime = block.timestamp;
74 | proposal.endTime = block.timestamp + votingPeriod;
75 |
76 | emit ProposalCreated(proposalCount, msg.sender, description);
77 | }
78 |
79 | function castVote(uint256 proposalId, bool support) external {
80 | Proposal storage proposal = proposals[proposalId];
81 | require(block.timestamp <= proposal.endTime, "Voting period ended");
82 | require(!proposal.hasVoted[msg.sender], "Already voted");
83 | require(votingPower[msg.sender] > 0, "No voting power");
84 |
85 | uint256 weight = votingPower[msg.sender];
86 | if (support) {
87 | proposal.forVotes += weight;
88 | } else {
89 | proposal.againstVotes += weight;
90 | }
91 |
92 | proposal.hasVoted[msg.sender] = true;
93 | proposal.stakedAmount[msg.sender] = userStakes[msg.sender];
94 |
95 | emit VoteCast(proposalId, msg.sender, support, weight);
96 | }
97 |
98 | function executeProposal(uint256 proposalId) external {
99 | Proposal storage proposal = proposals[proposalId];
100 | require(block.timestamp > proposal.endTime, "Voting period not ended");
101 | require(!proposal.executed, "Proposal already executed");
102 |
103 | proposal.executed = true;
104 |
105 | emit ProposalExecuted(proposalId);
106 | }
107 |
108 | // Helper Functions
109 | function calculateVotingPower(address user) public view returns (uint256) {
110 | return userStakes[user];
111 | }
112 |
113 | function canUnstake(address user, uint256 amount) internal view returns (bool) {
114 | uint256 lockedAmount = 0;
115 | for (uint256 i = 1; i <= proposalCount; i++) {
116 | Proposal storage proposal = proposals[i];
117 | if (!proposal.executed && proposal.hasVoted[user]) {
118 | lockedAmount += proposal.stakedAmount[user];
119 | }
120 | }
121 | return userStakes[user] - lockedAmount >= amount;
122 | }
123 |
124 | // Admin Functions
125 | function updateMinimumStakeForProposal(uint256 _newAmount) external onlyOwner {
126 | minimumStakeForProposal = _newAmount;
127 | }
128 |
129 | function updateVotingPeriod(uint256 _newPeriod) external onlyOwner {
130 | votingPeriod = _newPeriod;
131 | }
132 | }
--------------------------------------------------------------------------------
/docs/API.md:
--------------------------------------------------------------------------------
1 | # DeepRug API Documentation
2 |
3 | ## Smart Contract Interfaces
4 |
5 | ### FollowTrade Contract
6 |
7 | #### State Variables
8 |
9 | - `owner` (address): Contract owner's address
10 | - `followFee` (uint256): Fee required for following trades
11 | - `burnRate` (uint256): Token burn rate (0-50%)
12 | - `totalBurned` (uint256): Total amount of tokens burned
13 | - `balances` (mapping): User balance mapping
14 | - `activeFollows` (mapping): User active follow status
15 | - `traderRewards` (mapping): Trader reward balances
16 |
17 | #### Events
18 |
19 | ```solidity
20 | event FollowTradeStarted(address follower, string symbol, uint256 fee)
21 | event ProfitDistributed(address trader, address follower, uint256 amount)
22 | event TokensBurned(uint256 amount)
23 | event RewardsWithdrawn(address user, uint256 amount)
24 | ```
25 |
26 | #### Functions
27 |
28 | ##### startFollow
29 | ```solidity
30 | function startFollow(string memory symbol) external payable
31 | ```
32 | Start following a trade.
33 | - Parameters:
34 | - `symbol`: Trading pair symbol
35 | - Requirements:
36 | - Paid fee must be greater than or equal to followFee
37 | - User cannot follow the same trading pair multiple times
38 |
39 | ##### distributeProfits
40 | ```solidity
41 | function distributeProfits(address[] calldata followers, uint256[] calldata amounts) external onlyOwner
42 | ```
43 | Distribute profits.
44 | - Parameters:
45 | - `followers`: Array of follower addresses
46 | - `amounts`: Array of corresponding profit amounts
47 | - Distribution rules:
48 | - Trader receives 70% of profits
49 | - Follower receives 30% of profits
50 |
51 | ##### withdrawRewards
52 | ```solidity
53 | function withdrawRewards() external
54 | ```
55 | Withdraw trading rewards.
56 |
57 | ##### withdraw
58 | ```solidity
59 | function withdraw() external
60 | ```
61 | Withdraw account balance.
62 |
63 | ##### updateFollowFee
64 | ```solidity
65 | function updateFollowFee(uint256 _newFee) external onlyOwner
66 | ```
67 | Update follow fee.
68 |
69 | ##### updateBurnRate
70 | ```solidity
71 | function updateBurnRate(uint256 _newRate) external onlyOwner
72 | ```
73 | Update token burn rate.
74 |
75 | ## Trading Service API
76 |
77 | ### WebSocket Interface
78 |
79 | #### Connection
80 | ```javascript
81 | ws://localhost:8081
82 | ```
83 |
84 | #### Message Types
85 |
86 | ##### Follow Request
87 | ```javascript
88 | {
89 | "type": "follow_request",
90 | "trader": "",
91 | "symbol": "",
92 | "publicKey": ""
93 | }
94 | ```
95 |
96 | ##### Unfollow Request
97 | ```javascript
98 | {
99 | "type": "unfollow_request",
100 | "trader": "",
101 | "symbol": ""
102 | }
103 | ```
104 |
105 | ---
106 |
107 | [点击查看中文文档]
108 |
109 | # DeepRug API 文档
110 |
111 | ## 智能合约接口
112 |
113 | ### 跟随交易合约
114 |
115 | #### 状态变量
116 |
117 | - `owner` (address): 合约所有者地址
118 | - `followFee` (uint256): 跟随交易所需的费用
119 | - `burnRate` (uint256): 代币销毁比率(0-50%)
120 | - `totalBurned` (uint256): 已销毁代币总量
121 | - `balances` (mapping): 用户余额映射
122 | - `activeFollows` (mapping): 用户活跃跟随状态
123 | - `traderRewards` (mapping): 交易者奖励余额
124 |
125 | #### 事件
126 |
127 | ```solidity
128 | event FollowTradeStarted(address follower, string symbol, uint256 fee)
129 | event ProfitDistributed(address trader, address follower, uint256 amount)
130 | event TokensBurned(uint256 amount)
131 | event RewardsWithdrawn(address user, uint256 amount)
132 | ```
133 |
134 | 事件说明:
135 | - FollowTradeStarted:开始跟随交易时触发
136 | - ProfitDistributed:分配利润时触发
137 | - TokensBurned:代币销毁时触发
138 | - RewardsWithdrawn:提取奖励时触发
139 |
140 | #### 函数
141 |
142 | ##### 开始跟随
143 | ```solidity
144 | function startFollow(string memory symbol) external payable
145 | ```
146 | 开始跟随一个交易。
147 | - 参数:
148 | - `symbol`: 交易对符号
149 | - 要求:
150 | - 支付的费用必须大于或等于跟随费用
151 | - 用户不能多次跟随同一个交易对
152 |
153 | ##### 分配利润
154 | ```solidity
155 | function distributeProfits(address[] calldata followers, uint256[] calldata amounts) external onlyOwner
156 | ```
157 | 分配利润。
158 | - 参数:
159 | - `followers`: 跟随者地址数组
160 | - `amounts`: 对应的利润金额数组
161 | - 分配规则:
162 | - 交易者获得70%的利润
163 | - 跟随者获得30%的利润
164 |
165 | ##### 提取奖励
166 | ```solidity
167 | function withdrawRewards() external
168 | ```
169 | 提取交易奖励。
170 |
171 | ##### 提取余额
172 | ```solidity
173 | function withdraw() external
174 | ```
175 | 提取账户余额。
176 |
177 | ##### 更新跟随费用
178 | ```solidity
179 | function updateFollowFee(uint256 _newFee) external onlyOwner
180 | ```
181 | 更新跟随费用。
182 |
183 | ##### 更新销毁比率
184 | ```solidity
185 | function updateBurnRate(uint256 _newRate) external onlyOwner
186 | ```
187 | 更新代币销毁比率。
188 |
189 | ## 交易服务API
190 |
191 | ### WebSocket接口
192 |
193 | #### 连接
194 | ```javascript
195 | ws://localhost:8081
196 | ```
197 |
198 | #### 消息类型
199 |
200 | ##### 跟随请求
201 | ```javascript
202 | {
203 | "type": "follow_request",
204 | "trader": "",
205 | "symbol": "",
206 | "publicKey": ""
207 | }
208 | ```
209 |
210 | ##### 取消跟随请求
211 | ```javascript
212 | {
213 | "type": "unfollow_request",
214 | "trader": "",
215 | "symbol": ""
216 | }
217 | ```
--------------------------------------------------------------------------------
/docs/DEVELOPER.md:
--------------------------------------------------------------------------------
1 | # DeepRug Developer Documentation
2 |
3 | ## Project Architecture
4 |
5 | ### System Components
6 |
7 | 1. Smart Contracts
8 | - FollowTrade.sol: Core contract for follow trading
9 | - Implements user following, profit distribution, token burning functionalities
10 |
11 | 2. Trading Engine
12 | - Located in src/ai_engine directory
13 | - market_data.py: Market data collection and processing
14 | - ml_models.py: Machine learning models
15 | - risk_manager.py: Risk management module
16 | - trading_engine.py: Trading strategy execution
17 |
18 | 3. Service Layer
19 | - follow_trade_service.js: Follow trading service
20 | - trading_service.js: Trade execution service
21 |
22 | ### Tech Stack
23 |
24 | - Smart Contracts: Solidity ^0.8.0
25 | - Backend Services: Node.js
26 | - AI Engine: Python
27 | - WebSocket: Real-time communication
28 |
29 | ## Environment Setup
30 |
31 | ### Prerequisites
32 |
33 | - Node.js >= 14.0.0
34 | - Python >= 3.8
35 | - Solidity ^0.8.0
36 | - Hardhat or Truffle (Smart contract development framework)
37 |
38 | ### Dependencies Installation
39 |
40 | 1. Install Node.js dependencies
41 | ```bash
42 | npm install
43 | ```
44 |
45 | 2. Install Python dependencies
46 | ```bash
47 | pip install -r requirements.txt
48 | ```
49 |
50 | ## Local Development
51 |
52 | ### 1. Start Local Blockchain
53 | ```bash
54 | npx hardhat node
55 | ```
56 |
57 | ### 2. Deploy Smart Contracts
58 | ```bash
59 | npx hardhat run scripts/deploy.js --network localhost
60 | ```
61 |
62 | ### 3. Start Trading Service
63 | ```bash
64 | node src/index.js
65 | ```
66 |
67 | ### 4. Start AI Engine
68 | ```bash
69 | python src/ai_engine/trading_engine.py
70 | ```
71 |
72 | ## Testing
73 |
74 | ### Smart Contract Tests
75 | ```bash
76 | npx hardhat test
77 | ```
78 |
79 | ### AI Engine Tests
80 | ```bash
81 | python -m pytest tests/ai_engine
82 | ```
83 |
84 | ## Deployment Process
85 |
86 | ### 1. Prepare Environment Variables
87 | Create .env file:
88 | ```
89 | PRIVATE_KEY=your_private_key
90 | INFURA_API_KEY=your_infura_key
91 | FOLLOW_FEE=1000000000000000000
92 | BURN_RATE=10
93 | ```
94 |
95 | ### 2. Compile Contracts
96 | ```bash
97 | npx hardhat compile
98 | ```
99 |
100 | ### 3. Deploy to Testnet
101 | ```bash
102 | npx hardhat run scripts/deploy.js --network testnet
103 | ```
104 |
105 | ---
106 |
107 | [点击查看中文文档]
108 |
109 | # DeepRug 开发者文档
110 |
111 | ## 项目架构
112 |
113 | ### 系统组件
114 |
115 | 1. 智能合约
116 | - FollowTrade.sol: 跟随交易的核心合约
117 | - 实现用户跟随、利润分配、代币销毁等功能
118 |
119 | 2. 交易引擎
120 | - 位于src/ai_engine目录
121 | - market_data.py: 市场数据收集和处理
122 | - ml_models.py: 机器学习模型
123 | - risk_manager.py: 风险管理模块
124 | - trading_engine.py: 交易策略执行
125 |
126 | 3. 服务层
127 | - follow_trade_service.js: 跟随交易服务
128 | - trading_service.js: 交易执行服务
129 |
130 | ### 技术栈
131 |
132 | - 智能合约: Solidity ^0.8.0
133 | - 后端服务: Node.js
134 | - AI引擎: Python
135 | - WebSocket: 实时通信
136 |
137 | ## 环境配置
138 |
139 | ### 前置要求
140 |
141 | - Node.js >= 14.0.0
142 | - Python >= 3.8
143 | - Solidity ^0.8.0
144 | - Hardhat 或 Truffle (智能合约开发框架)
145 |
146 | ### 依赖安装
147 |
148 | 1. 安装Node.js依赖
149 | ```bash
150 | npm install
151 | ```
152 |
153 | 2. 安装Python依赖
154 | ```bash
155 | pip install -r requirements.txt
156 | ```
157 |
158 | ## 本地开发
159 |
160 | ### 1. 启动本地区块链
161 | ```bash
162 | npx hardhat node
163 | ```
164 |
165 | ### 2. 部署智能合约
166 | ```bash
167 | npx hardhat run scripts/deploy.js --network localhost
168 | ```
169 |
170 | ### 3. 启动交易服务
171 | ```bash
172 | node src/index.js
173 | ```
174 |
175 | ### 4. 启动AI引擎
176 | ```bash
177 | python src/ai_engine/trading_engine.py
178 | ```
179 |
180 | ## 测试
181 |
182 | ### 智能合约测试
183 | ```bash
184 | npx hardhat test
185 | ```
186 |
187 | ### AI引擎测试
188 | ```bash
189 | python -m pytest tests/ai_engine
190 | ```
191 |
192 | ## 部署流程
193 |
194 | ### 1. 准备环境变量
195 | 创建.env文件:
196 | ```
197 | PRIVATE_KEY=你的私钥
198 | INFURA_API_KEY=你的Infura密钥
199 | FOLLOW_FEE=1000000000000000000
200 | BURN_RATE=10
201 | ```
202 |
203 | ### 2. 编译合约
204 | ```bash
205 | npx hardhat compile
206 | ```
207 |
208 | ### 3. 部署到测试网
209 | ```bash
210 | npx hardhat run scripts/deploy.js --network testnet
211 | ```
212 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "deeprug",
3 | "version": "0.1.0",
4 | "description": "A revolutionary AI quantitative trading platform that perfectly combines AI trading strategies with social entertainment",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "node src/index.js",
8 | "test": "jest",
9 | "dev": "nodemon src/index.js"
10 | },
11 | "keywords": [
12 | "AI",
13 | "trading",
14 | "blockchain",
15 | "DeepSeek",
16 | "cryptocurrency"
17 | ],
18 | "author": "DeepRug Team",
19 | "license": "MIT",
20 | "dependencies": {
21 | "express": "^4.18.2",
22 | "web3": "^4.1.1",
23 | "socket.io": "^4.7.2",
24 | "mongoose": "^7.5.0",
25 | "axios": "^1.5.0",
26 | "dotenv": "^16.3.1"
27 | },
28 | "devDependencies": {
29 | "jest": "^29.6.4",
30 | "nodemon": "^3.0.1",
31 | "eslint": "^8.48.0"
32 | }
33 | }
--------------------------------------------------------------------------------
/program/src/follow_trade.rs:
--------------------------------------------------------------------------------
1 | use anchor_lang::prelude::*;
2 | use anchor_spl::token::{self, Token, TokenAccount, Transfer};
3 |
4 | #[program]
5 | pub mod follow_trade {
6 | use super::*;
7 |
8 | pub fn initialize(
9 | ctx: Context,
10 | follow_fee: u64,
11 | burn_rate: u8,
12 | ) -> Result<()> {
13 | let state = &mut ctx.accounts.state;
14 | state.owner = ctx.accounts.owner.key();
15 | state.follow_fee = follow_fee;
16 | state.burn_rate = burn_rate;
17 | state.total_followers = 0;
18 | Ok(())
19 | }
20 |
21 | pub fn start_follow(
22 | ctx: Context,
23 | symbol: String,
24 | ) -> Result<()> {
25 | let follow = &mut ctx.accounts.follow;
26 | follow.trader = ctx.accounts.trader.key();
27 | follow.follower = ctx.accounts.follower.key();
28 | follow.symbol = symbol;
29 | follow.active = true;
30 | follow.timestamp = Clock::get()?.unix_timestamp;
31 |
32 | let state = &mut ctx.accounts.state;
33 | state.total_followers = state.total_followers.checked_add(1).unwrap();
34 |
35 | emit!(FollowStarted {
36 | trader: follow.trader,
37 | follower: follow.follower,
38 | symbol: follow.symbol.clone(),
39 | timestamp: follow.timestamp,
40 | });
41 |
42 | Ok(())
43 | }
44 |
45 | pub fn distribute_profit(
46 | ctx: Context,
47 | amount: u64,
48 | ) -> Result<()> {
49 | let follow = &ctx.accounts.follow;
50 | require!(follow.active, ErrorCode::FollowNotActive);
51 |
52 | // Calculate profit share
53 | let trader_share = (amount * 70) / 100; // 70% to trader
54 | let follower_share = amount - trader_share; // 30% to follower
55 |
56 | // Transfer profit shares
57 | token::transfer(
58 | CpiContext::new(
59 | ctx.accounts.token_program.to_account_info(),
60 | Transfer {
61 | from: ctx.accounts.profit_pool.to_account_info(),
62 | to: ctx.accounts.trader_token.to_account_info(),
63 | authority: ctx.accounts.state.to_account_info(),
64 | },
65 | ),
66 | trader_share,
67 | )?;
68 |
69 | token::transfer(
70 | CpiContext::new(
71 | ctx.accounts.token_program.to_account_info(),
72 | Transfer {
73 | from: ctx.accounts.profit_pool.to_account_info(),
74 | to: ctx.accounts.follower_token.to_account_info(),
75 | authority: ctx.accounts.state.to_account_info(),
76 | },
77 | ),
78 | follower_share,
79 | )?;
80 |
81 | emit!(ProfitDistributed {
82 | trader: follow.trader,
83 | follower: follow.follower,
84 | amount,
85 | trader_share,
86 | follower_share,
87 | });
88 |
89 | Ok(())
90 | }
91 | }
92 |
93 | #[derive(Accounts)]
94 | pub struct Initialize<'info> {
95 | #[account(init, payer = owner, space = 8 + State::LEN)]
96 | pub state: Account<'info, State>,
97 | #[account(mut)]
98 | pub owner: Signer<'info>,
99 | pub system_program: Program<'info, System>,
100 | }
101 |
102 | #[derive(Accounts)]
103 | pub struct StartFollow<'info> {
104 | #[account(init, payer = follower, space = 8 + Follow::LEN)]
105 | pub follow: Account<'info, Follow>,
106 | #[account(mut)]
107 | pub state: Account<'info, State>,
108 | pub trader: AccountInfo<'info>,
109 | #[account(mut)]
110 | pub follower: Signer<'info>,
111 | pub system_program: Program<'info, System>,
112 | }
113 |
114 | #[derive(Accounts)]
115 | pub struct DistributeProfit<'info> {
116 | #[account(mut)]
117 | pub follow: Account<'info, Follow>,
118 | #[account(mut)]
119 | pub state: Account<'info, State>,
120 | #[account(mut)]
121 | pub profit_pool: Account<'info, TokenAccount>,
122 | #[account(mut)]
123 | pub trader_token: Account<'info, TokenAccount>,
124 | #[account(mut)]
125 | pub follower_token: Account<'info, TokenAccount>,
126 | pub token_program: Program<'info, Token>,
127 | }
128 |
129 | #[account]
130 | pub struct State {
131 | pub owner: Pubkey,
132 | pub follow_fee: u64,
133 | pub burn_rate: u8,
134 | pub total_followers: u64,
135 | }
136 |
137 | #[account]
138 | pub struct Follow {
139 | pub trader: Pubkey,
140 | pub follower: Pubkey,
141 | pub symbol: String,
142 | pub active: bool,
143 | pub timestamp: i64,
144 | }
145 |
146 | #[event]
147 | pub struct FollowStarted {
148 | pub trader: Pubkey,
149 | pub follower: Pubkey,
150 | pub symbol: String,
151 | pub timestamp: i64,
152 | }
153 |
154 | #[event]
155 | pub struct ProfitDistributed {
156 | pub trader: Pubkey,
157 | pub follower: Pubkey,
158 | pub amount: u64,
159 | pub trader_share: u64,
160 | pub follower_share: u64,
161 | }
162 |
163 | #[error_code]
164 | pub enum ErrorCode {
165 | #[msg("Follow is not active")]
166 | FollowNotActive,
167 | }
--------------------------------------------------------------------------------
/program/src/lib.rs:
--------------------------------------------------------------------------------
1 | use anchor_lang::prelude::*;
2 | use anchor_spl::token::{self, Burn, Mint, Token, TokenAccount, Transfer};
3 |
4 | declare_id!("RUGTokenProgramID111111111111111111111111111111");
5 |
6 | #[program]
7 | pub mod rug_token {
8 | use super::*;
9 |
10 | pub fn initialize(
11 | ctx: Context,
12 | initial_supply: u64,
13 | follow_trade_fee: u64,
14 | burn_rate: u8,
15 | ) -> Result<()> {
16 | let token_program = &ctx.program;
17 | let token_mint = &ctx.accounts.mint;
18 | let owner = &ctx.accounts.owner;
19 |
20 | // Initialize state
21 | let state = &mut ctx.accounts.state;
22 | state.owner = owner.key();
23 | state.follow_trade_fee = follow_trade_fee;
24 | state.burn_rate = burn_rate;
25 | state.trading_system = Pubkey::default();
26 |
27 | // Mint initial supply to owner
28 | token::mint_to(
29 | CpiContext::new(
30 | token_program.to_account_info(),
31 | token::MintTo {
32 | mint: token_mint.to_account_info(),
33 | to: owner.to_account_info(),
34 | authority: token_mint.to_account_info(),
35 | },
36 | ),
37 | initial_supply,
38 | )?;
39 |
40 | Ok(())
41 | }
42 |
43 | pub fn set_trading_system(
44 | ctx: Context,
45 | trading_system: Pubkey,
46 | ) -> Result<()> {
47 | require!(trading_system != Pubkey::default(), "Invalid address");
48 | let state = &mut ctx.accounts.state;
49 | state.trading_system = trading_system;
50 | Ok(())
51 | }
52 |
53 | pub fn pay_follow_trade_fee(ctx: Context) -> Result<()> {
54 | let state = &ctx.accounts.state;
55 | let fee = state.follow_trade_fee;
56 | let burn_amount = (fee * state.burn_rate as u64) / 100;
57 | let system_amount = fee - burn_amount;
58 |
59 | // Burn tokens
60 | token::burn(
61 | CpiContext::new(
62 | ctx.accounts.token_program.to_account_info(),
63 | Burn {
64 | mint: ctx.accounts.mint.to_account_info(),
65 | from: ctx.accounts.user_token_account.to_account_info(),
66 | authority: ctx.accounts.user.to_account_info(),
67 | },
68 | ),
69 | burn_amount,
70 | )?;
71 |
72 | // Transfer to trading system
73 | token::transfer(
74 | CpiContext::new(
75 | ctx.accounts.token_program.to_account_info(),
76 | Transfer {
77 | from: ctx.accounts.user_token_account.to_account_info(),
78 | to: ctx.accounts.trading_system_token_account.to_account_info(),
79 | authority: ctx.accounts.user.to_account_info(),
80 | },
81 | ),
82 | system_amount,
83 | )?;
84 |
85 | emit!(FollowTradeFeePaid {
86 | user: ctx.accounts.user.key(),
87 | amount: fee,
88 | });
89 |
90 | Ok(())
91 | }
92 |
93 | pub fn update_follow_trade_fee(
94 | ctx: Context,
95 | new_fee: u64,
96 | ) -> Result<()> {
97 | let state = &mut ctx.accounts.state;
98 | state.follow_trade_fee = new_fee;
99 | Ok(())
100 | }
101 |
102 | pub fn update_burn_rate(
103 | ctx: Context,
104 | new_rate: u8,
105 | ) -> Result<()> {
106 | require!(new_rate <= 100, "Burn rate cannot exceed 100%");
107 | let state = &mut ctx.accounts.state;
108 | state.burn_rate = new_rate;
109 | Ok(())
110 | }
111 | }
112 |
113 | #[derive(Accounts)]
114 | pub struct Initialize<'info> {
115 | #[account(init, payer = owner, space = 8 + TokenState::LEN)]
116 | pub state: Account<'info, TokenState>,
117 | #[account(mut)]
118 | pub mint: Account<'info, Mint>,
119 | #[account(mut)]
120 | pub owner: Signer<'info>,
121 | pub system_program: Program<'info, System>,
122 | pub token_program: Program<'info, Token>,
123 | }
124 |
125 | #[derive(Accounts)]
126 | pub struct SetTradingSystem<'info> {
127 | #[account(mut, has_one = owner)]
128 | pub state: Account<'info, TokenState>,
129 | pub owner: Signer<'info>,
130 | }
131 |
132 | #[derive(Accounts)]
133 | pub struct PayFollowTradeFee<'info> {
134 | #[account(mut)]
135 | pub state: Account<'info, TokenState>,
136 | #[account(mut)]
137 | pub mint: Account<'info, Mint>,
138 | #[account(mut)]
139 | pub user_token_account: Account<'info, TokenAccount>,
140 | #[account(mut)]
141 | pub trading_system_token_account: Account<'info, TokenAccount>,
142 | pub user: Signer<'info>,
143 | pub token_program: Program<'info, Token>,
144 | }
145 |
146 | #[derive(Accounts)]
147 | pub struct UpdateFollowTradeFee<'info> {
148 | #[account(mut, has_one = owner)]
149 | pub state: Account<'info, TokenState>,
150 | pub owner: Signer<'info>,
151 | }
152 |
153 | #[derive(Accounts)]
154 | pub struct UpdateBurnRate<'info> {
155 | #[account(mut, has_one = owner)]
156 | pub state: Account<'info, TokenState>,
157 | pub owner: Signer<'info>,
158 | }
159 |
160 | #[account]
161 | pub struct TokenState {
162 | pub owner: Pubkey,
163 | pub follow_trade_fee: u64,
164 | pub burn_rate: u8,
165 | pub trading_system: Pubkey,
166 | }
167 |
168 | impl TokenState {
169 | pub const LEN: usize = 32 + 8 + 1 + 32;
170 | }
171 |
172 | #[event]
173 | pub struct FollowTradeFeePaid {
174 | pub user: Pubkey,
175 | pub amount: u64,
176 | }
177 |
178 | #[event]
179 | pub struct TokensBurned {
180 | pub amount: u64,
181 | }
--------------------------------------------------------------------------------
/src/ai_engine/market_data.py:
--------------------------------------------------------------------------------
1 | import ccxt
2 | import numpy as np
3 | import pandas as pd
4 | from datetime import datetime, timedelta
5 | import logging
6 |
7 | class MarketDataCollector:
8 | def __init__(self, exchange_id='binance', api_key=None, api_secret=None):
9 | self.exchange = getattr(ccxt, exchange_id)({
10 | 'apiKey': api_key,
11 | 'secret': api_secret,
12 | 'enableRateLimit': True,
13 | 'options': {'defaultType': 'future'}
14 | })
15 | self.logger = logging.getLogger(__name__)
16 |
17 | def fetch_historical_data(self, symbol, timeframe='1h', limit=1000):
18 | """获取历史K线数据"""
19 | try:
20 | ohlcv = self.exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
21 | return self._convert_to_dataframe(ohlcv)
22 | except Exception as e:
23 | self.logger.error(f"Error fetching historical data: {str(e)}")
24 | return None
25 |
26 | def fetch_orderbook(self, symbol, limit=20):
27 | """获取市场深度数据"""
28 | try:
29 | orderbook = self.exchange.fetch_order_book(symbol, limit=limit)
30 | return {
31 | 'bids': np.array(orderbook['bids']),
32 | 'asks': np.array(orderbook['asks']),
33 | 'timestamp': orderbook['timestamp']
34 | }
35 | except Exception as e:
36 | self.logger.error(f"Error fetching orderbook: {str(e)}")
37 | return None
38 |
39 | def fetch_recent_trades(self, symbol, limit=100):
40 | """获取最近成交数据"""
41 | try:
42 | trades = self.exchange.fetch_trades(symbol, limit=limit)
43 | return pd.DataFrame(trades)
44 | except Exception as e:
45 | self.logger.error(f"Error fetching recent trades: {str(e)}")
46 | return None
47 |
48 | def _convert_to_dataframe(self, ohlcv):
49 | """将OHLCV数据转换为DataFrame格式"""
50 | df = pd.DataFrame(ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
51 | df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
52 | return df
53 |
54 | def calculate_vwap(self, trades_df):
55 | """计算成交量加权平均价格"""
56 | if trades_df is None or trades_df.empty:
57 | return None
58 |
59 | trades_df['vwap'] = (trades_df['price'] * trades_df['amount']).cumsum() / trades_df['amount'].cumsum()
60 | return trades_df['vwap'].iloc[-1]
61 |
62 | def calculate_market_impact(self, orderbook, trade_size):
63 | """计算市场冲击成本"""
64 | if orderbook is None:
65 | return None
66 |
67 | bids, asks = orderbook['bids'], orderbook['asks']
68 |
69 | def calculate_impact(orders, size, side='buy'):
70 | remaining_size = size
71 | total_cost = 0
72 | for price, volume in orders:
73 | if remaining_size <= 0:
74 | break
75 | executed = min(remaining_size, volume)
76 | total_cost += executed * price
77 | remaining_size -= executed
78 | return total_cost / size if remaining_size <= 0 else None
79 |
80 | buy_impact = calculate_impact(asks, trade_size, 'buy')
81 | sell_impact = calculate_impact(bids, trade_size, 'sell')
82 |
83 | return {
84 | 'buy_impact': buy_impact,
85 | 'sell_impact': sell_impact
86 | }
--------------------------------------------------------------------------------
/src/ai_engine/meme_generator.py:
--------------------------------------------------------------------------------
1 | import os
2 | import random
3 | from PIL import Image, ImageDraw, ImageFont
4 | from transformers import pipeline
5 |
6 | class MemeGenerator:
7 | def __init__(self):
8 | self.sentiment_analyzer = pipeline('sentiment-analysis')
9 | self.text_generator = pipeline('text-generation')
10 | self.templates_dir = os.path.join(os.path.dirname(__file__), 'meme_templates')
11 | self.fonts_dir = os.path.join(os.path.dirname(__file__), 'fonts')
12 |
13 | def analyze_trade_sentiment(self, trade_data):
14 | """分析交易数据情绪"""
15 | trade_text = f"Trade {trade_data['symbol']} at {trade_data['price']} with {trade_data['profit_loss']}"
16 | sentiment = self.sentiment_analyzer(trade_text)[0]
17 | return sentiment['label'], sentiment['score']
18 |
19 | def generate_meme_text(self, sentiment, trade_data):
20 | """根据交易情绪生成嘲讽文本"""
21 | prompt_templates = {
22 | 'POSITIVE': [
23 | "When you make {profit} on {symbol} and others are still waiting for dips:",
24 | "Me watching my {symbol} position going to the moon:",
25 | "That moment when your {symbol} trade hits the target:"
26 | ],
27 | 'NEGATIVE': [
28 | "When you thought {symbol} was going up but it dumps instead:",
29 | "Me watching my {symbol} position getting liquidated:",
30 | "That feeling when you FOMO into {symbol} at the top:"
31 | ]
32 | }
33 |
34 | templates = prompt_templates['POSITIVE'] if sentiment == 'POSITIVE' else prompt_templates['NEGATIVE']
35 | template = random.choice(templates)
36 |
37 | return template.format(
38 | symbol=trade_data['symbol'],
39 | profit=trade_data.get('profit_loss', '0')
40 | )
41 |
42 | def create_meme(self, text, template_name='default.jpg', style='classic'):
43 | """创建Meme图片
44 | Args:
45 | text: 要添加的文本
46 | template_name: 模板图片名称
47 | style: 文字样式 ('classic', 'modern', 'minimal', 'bold')
48 | Returns:
49 | 生成的meme图片路径
50 | """
51 | try:
52 | # 加载模板图片
53 | template_path = os.path.join(self.templates_dir, template_name)
54 | image = Image.open(template_path)
55 | draw = ImageDraw.Draw(image)
56 |
57 | # 样式配置
58 | style_configs = {
59 | 'classic': {
60 | 'font': 'impact.ttf',
61 | 'size_ratio': 0.1,
62 | 'stroke_width': 2,
63 | 'text_color': 'white',
64 | 'stroke_color': 'black'
65 | },
66 | 'modern': {
67 | 'font': 'helvetica.ttf',
68 | 'size_ratio': 0.08,
69 | 'stroke_width': 0,
70 | 'text_color': 'white',
71 | 'shadow_offset': 3
72 | },
73 | 'minimal': {
74 | 'font': 'arial.ttf',
75 | 'size_ratio': 0.07,
76 | 'stroke_width': 1,
77 | 'text_color': 'black',
78 | 'background': True
79 | },
80 | 'bold': {
81 | 'font': 'futura.ttf',
82 | 'size_ratio': 0.12,
83 | 'stroke_width': 3,
84 | 'text_color': 'yellow',
85 | 'stroke_color': 'red'
86 | }
87 | }
88 |
89 | style_config = style_configs.get(style, style_configs['classic'])
90 |
91 | # 设置字体
92 | font_path = os.path.join(self.fonts_dir, style_config['font'])
93 | font_size = int(image.width * style_config['size_ratio'])
94 | font = ImageFont.truetype(font_path, font_size)
95 |
96 | # 创建绘图对象
97 | draw = ImageDraw.Draw(image)
98 |
99 | # 计算文本位置
100 | text_width = draw.textlength(text, font=font)
101 | x = (image.width - text_width) / 2
102 | y = image.height * 0.1 # 文本位置在顶部10%处
103 |
104 | # 绘制文本边框
105 | outline_size = int(font_size * 0.05)
106 | for adj in range(-outline_size, outline_size + 1):
107 | for opp in range(-outline_size, outline_size + 1):
108 | draw.text((x + adj, y + opp), text, font=font, fill='black')
109 |
110 | # 绘制主文本
111 | draw.text((x, y), text, font=font, fill='white')
112 |
113 | return image
114 |
115 | def generate_trade_meme(self, trade_data):
116 | """生成交易相关的Meme"""
117 | # 分析交易情绪
118 | sentiment, _ = self.analyze_trade_sentiment(trade_data)
119 |
120 | # 生成Meme文本
121 | meme_text = self.generate_meme_text(sentiment, trade_data)
122 |
123 | # 选择合适的模板
124 | template_name = 'bullish.jpg' if sentiment == 'POSITIVE' else 'bearish.jpg'
125 |
126 | # 创建Meme
127 | meme = self.create_meme(meme_text, template_name)
128 |
129 | return meme
130 |
131 | def save_meme(self, meme, output_path):
132 | """保存Meme图片"""
133 | meme.save(output_path, quality=95)
134 | return output_path
--------------------------------------------------------------------------------
/src/ai_engine/ml_models.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
3 | from sklearn.preprocessing import StandardScaler
4 | from sklearn.model_selection import cross_val_score, TimeSeriesSplit
5 | from sklearn.metrics import precision_score, recall_score, f1_score
6 | import joblib
7 | import logging
8 |
9 | class MLPredictor:
10 | def __init__(self):
11 | self.models = {
12 | 'rf': RandomForestClassifier(n_estimators=100, max_depth=10, random_state=42),
13 | 'gb': GradientBoostingClassifier(n_estimators=100, learning_rate=0.1, random_state=42)
14 | }
15 | self.scaler = StandardScaler()
16 | self.logger = logging.getLogger(__name__)
17 | self.selected_model = 'rf'
18 |
19 | def prepare_features(self, technical_indicators):
20 | """Prepare features for ML model"""
21 | try:
22 | # Extract basic features
23 | basic_features = [
24 | technical_indicators['sma_20'],
25 | technical_indicators['sma_50'],
26 | technical_indicators['rsi'],
27 | technical_indicators['volatility']
28 | ]
29 |
30 | # Calculate advanced features
31 | sma_ratio = technical_indicators['sma_20'] / technical_indicators['sma_50'] if technical_indicators['sma_50'] else 1.0
32 | rsi_momentum = 1 if technical_indicators['rsi'] > 50 else -1 if technical_indicators['rsi'] < 50 else 0
33 | volatility_factor = np.log1p(technical_indicators['volatility']) if technical_indicators['volatility'] else 0
34 |
35 | # Add MACD features
36 | macd_signal = 1 if technical_indicators['macd'] > technical_indicators['macd_signal'] else -1
37 | macd_trend = np.sign(technical_indicators['macd'])
38 |
39 | # Add volume and price features
40 | volume_trend = np.sign(technical_indicators['obv'])
41 | price_momentum = technical_indicators['close'] / technical_indicators['sma_20'] - 1
42 |
43 | # Combine all features
44 | features = basic_features + [
45 | sma_ratio,
46 | rsi_momentum,
47 | volatility_factor,
48 | macd_signal,
49 | macd_trend,
50 | volume_trend,
51 | price_momentum
52 | ]
53 | features = np.array(features).reshape(1, -1)
54 |
55 | # Handle missing values
56 | features = np.nan_to_num(features, nan=0.0)
57 |
58 | return self.scaler.transform(features)
59 | except Exception as e:
60 | self.logger.error(f"Error preparing features: {str(e)}")
61 | return None
62 |
63 | def predict(self, features):
64 | """Make price movement prediction with confidence score"""
65 | try:
66 | if features is None:
67 | return None, 0.0
68 |
69 | model = self.models[self.selected_model]
70 | prediction = model.predict(features)[0]
71 | confidence = np.max(model.predict_proba(features)[0])
72 |
73 | return prediction, confidence
74 | except Exception as e:
75 | self.logger.error(f"Error making prediction: {str(e)}")
76 | return None, 0.0
77 |
78 | def evaluate_model(self, X, y):
79 | """Evaluate model performance using time series cross-validation"""
80 | try:
81 | tscv = TimeSeriesSplit(n_splits=5)
82 | scores = cross_val_score(self.models[self.selected_model], X, y, cv=tscv)
83 |
84 | y_pred = self.models[self.selected_model].predict(X)
85 | precision = precision_score(y, y_pred, average='weighted')
86 | recall = recall_score(y, y_pred, average='weighted')
87 | f1 = f1_score(y, y_pred, average='weighted')
88 |
89 | return {
90 | 'cv_scores': scores,
91 | 'cv_mean': scores.mean(),
92 | 'cv_std': scores.std(),
93 | 'precision': precision,
94 | 'recall': recall,
95 | 'f1_score': f1
96 | }
97 | except Exception as e:
98 | self.logger.error(f"Error evaluating model: {str(e)}")
99 | return None
100 |
101 | def train(self, X, y):
102 | """Train the ML model with cross-validation"""
103 | try:
104 | X_scaled = self.scaler.fit_transform(X)
105 |
106 | # Perform cross-validation
107 | cv_scores = cross_val_score(self.model, X_scaled, y, cv=5)
108 | self.logger.info(f"Cross-validation scores: {cv_scores.mean():.3f} (+/- {cv_scores.std() * 2:.3f})")
109 |
110 | # Train final model
111 | self.model.fit(X_scaled, y)
112 |
113 | # Calculate performance metrics
114 | y_pred = self.model.predict(X_scaled)
115 | precision = precision_score(y, y_pred, average='weighted')
116 | recall = recall_score(y, y_pred, average='weighted')
117 | f1 = f1_score(y, y_pred, average='weighted')
118 |
119 | self.logger.info(f"Model performance - Precision: {precision:.3f}, Recall: {recall:.3f}, F1: {f1:.3f}")
120 |
121 | except Exception as e:
122 | self.logger.error(f"Error training model: {str(e)}")
123 |
124 | def save_model(self, path):
125 | """Save model and scaler to file"""
126 | try:
127 | model_path = f"{path}_model.joblib"
128 | scaler_path = f"{path}_scaler.joblib"
129 |
130 | joblib.dump(self.model, model_path)
131 | joblib.dump(self.scaler, scaler_path)
132 | self.logger.info(f"Model saved to {model_path}")
133 | except Exception as e:
134 | self.logger.error(f"Error saving model: {str(e)}")
135 |
136 | def load_model(self, path):
137 | """Load model and scaler from file"""
138 | try:
139 | model_path = f"{path}_model.joblib"
140 | scaler_path = f"{path}_scaler.joblib"
141 |
142 | self.model = joblib.load(model_path)
143 | self.scaler = joblib.load(scaler_path)
144 | self.logger.info(f"Model loaded from {model_path}")
145 | except Exception as e:
146 | self.logger.error(f"Error loading model: {str(e)}")
147 |
148 | def update_features(self, market_data):
149 | """Update model features with new market data"""
150 | try:
151 | if not market_data or 'close' not in market_data:
152 | return False
153 |
154 | # Extract new features
155 | close_prices = market_data['close']
156 | returns = np.diff(close_prices) / close_prices[:-1]
157 |
158 | # Calculate labels for training
159 | future_returns = np.roll(returns, -1)
160 | labels = (future_returns > 0).astype(int)[:-1]
161 |
162 | # Prepare features
163 | features = self.prepare_features(market_data)
164 | if features is not None and len(labels) > 0:
165 | # Update model with new data
166 | self.model.partial_fit(features, labels)
167 | return True
168 |
169 | return False
170 | except Exception as e:
171 | self.logger.error(f"Error updating features: {str(e)}")
172 | return False
--------------------------------------------------------------------------------
/src/ai_engine/risk_manager.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import logging
3 | from datetime import datetime
4 |
5 | class RiskManager:
6 | def __init__(self, max_position_size=0.1, max_drawdown=0.02, stop_loss=0.01):
7 | self.max_position_size = max_position_size
8 | self.max_drawdown = max_drawdown
9 | self.stop_loss = stop_loss
10 | self.logger = logging.getLogger(__name__)
11 | self.position_history = []
12 | self.drawdown_history = []
13 | self.last_update = datetime.now()
14 | self.market_state = 'neutral'
15 |
16 | def calculate_position_size(self, portfolio_value, volatility, risk_score):
17 | """Calculate optimal position size based on dynamic risk assessment"""
18 | try:
19 | # Base position size
20 | base_size = portfolio_value * self.max_position_size
21 |
22 | # Dynamic volatility adjustment
23 | vol_factor = 1 / (1 + np.exp(volatility - 0.5)) # Sigmoid function for smooth scaling
24 |
25 | # Risk score adjustment with exponential decay
26 | risk_factor = np.exp(-2 * (1 - risk_score))
27 |
28 | # Market condition adjustment
29 | market_factor = self._assess_market_conditions()
30 |
31 | # Time decay factor
32 | time_factor = self._calculate_time_decay()
33 |
34 | # Calculate final position size
35 | position_size = base_size * vol_factor * risk_factor * market_factor * time_factor
36 |
37 | # Apply maximum position constraint
38 | max_allowed = portfolio_value * self.max_position_size
39 | position_size = min(position_size, max_allowed)
40 |
41 | self.position_history.append(position_size / portfolio_value)
42 | return position_size
43 | except Exception as e:
44 | self.logger.error(f"Error calculating position size: {str(e)}")
45 | return 0
46 |
47 | def calculate_stop_loss(self, entry_price, position_type='long', volatility=None):
48 | """Calculate dynamic stop loss based on market volatility and trend"""
49 | try:
50 | # Base stop loss percentage
51 | base_stop = self.stop_loss
52 |
53 | # Adjust for volatility if provided
54 | if volatility is not None:
55 | vol_adjustment = np.clip(volatility / 0.02, 0.5, 2.0)
56 | base_stop *= vol_adjustment
57 |
58 | # Calculate stop loss price
59 | if position_type == 'long':
60 | stop_price = entry_price * (1 - base_stop)
61 | else:
62 | stop_price = entry_price * (1 + base_stop)
63 |
64 | return stop_price
65 | except Exception as e:
66 | self.logger.error(f"Error calculating stop loss: {str(e)}")
67 | return None
68 |
69 | def _assess_market_conditions(self):
70 | """Assess current market conditions for risk adjustment"""
71 | try:
72 | # Analyze position history for trend
73 | if len(self.position_history) > 0:
74 | recent_positions = self.position_history[-10:]
75 | trend = np.mean(np.diff(recent_positions))
76 |
77 | if trend > 0.01:
78 | self.market_state = 'bullish'
79 | return 1.2
80 | elif trend < -0.01:
81 | self.market_state = 'bearish'
82 | return 0.8
83 |
84 | self.market_state = 'neutral'
85 | return 1.0
86 | except Exception as e:
87 | self.logger.error(f"Error assessing market conditions: {str(e)}")
88 | return 1.0
89 |
90 | def _calculate_time_decay(self):
91 | """Calculate time-based decay factor for risk adjustment"""
92 | try:
93 | time_diff = (datetime.now() - self.last_update).total_seconds() / 3600
94 | decay = np.exp(-0.1 * time_diff)
95 | return max(0.5, decay)
96 | except Exception as e:
97 | self.logger.error(f"Error calculating time decay: {str(e)}")
98 | return 1.0
99 |
100 | def update_drawdown(self, current_value, peak_value):
101 | """Update and monitor drawdown levels"""
102 | try:
103 | drawdown = (peak_value - current_value) / peak_value
104 | self.drawdown_history.append(drawdown)
105 |
106 | # Check if max drawdown exceeded
107 | if drawdown > self.max_drawdown:
108 | return False
109 |
110 | return True
111 | except Exception as e:
112 | self.logger.error(f"Error updating drawdown: {str(e)}")
113 | return True
114 |
115 | def get_risk_metrics(self):
116 | """Get current risk metrics summary"""
117 | return {
118 | 'market_state': self.market_state,
119 | 'current_drawdown': self.drawdown_history[-1] if self.drawdown_history else 0,
120 | 'max_historical_drawdown': max(self.drawdown_history) if self.drawdown_history else 0,
121 | 'position_utilization': np.mean(self.position_history[-10:]) if self.position_history else 0
122 | }
123 |
124 | def _calculate_atr(self, period=14):
125 | """Calculate Average True Range for dynamic stop loss"""
126 | try:
127 | if len(self.position_history) < period:
128 | return self.stop_loss
129 |
130 | # Calculate true range
131 | true_ranges = []
132 | for i in range(1, len(self.position_history)):
133 | true_range = abs(self.position_history[i] - self.position_history[i-1])
134 | true_ranges.append(true_range)
135 |
136 | return np.mean(true_ranges[-period:])
137 | except Exception as e:
138 | self.logger.error(f"Error calculating ATR: {str(e)}")
139 | return self.stop_loss
140 |
141 | def _assess_market_conditions(self):
142 | """Assess current market conditions for position sizing"""
143 | try:
144 | if len(self.position_history) < 10:
145 | return 1.0
146 |
147 | recent_positions = self.position_history[-10:]
148 | trend = np.mean(np.diff(recent_positions))
149 | volatility = np.std(recent_positions)
150 |
151 | # Update market state
152 | if volatility > np.mean(self.position_history) * 1.5:
153 | self.market_state = 'volatile'
154 | elif abs(trend) > np.std(self.position_history) * 2:
155 | self.market_state = 'trending'
156 | else:
157 | self.market_state = 'neutral'
158 |
159 | # Calculate market factor
160 | if self.market_state == 'volatile':
161 | return 0.7 # Reduce position size in volatile markets
162 | elif self.market_state == 'trending':
163 | return 1.2 if trend > 0 else 0.8
164 | return 1.0
165 | except Exception as e:
166 | self.logger.error(f"Error assessing market conditions: {str(e)}")
167 | return 1.0
168 |
169 | def _calculate_time_decay(self):
170 | """Calculate time decay factor for position sizing"""
171 | try:
172 | time_diff = (datetime.now() - self.last_update).total_seconds() / 3600
173 | decay_factor = np.exp(-0.1 * time_diff) # Exponential decay
174 | self.last_update = datetime.now()
175 | return max(0.5, decay_factor)
176 | except Exception as e:
177 | self.logger.error(f"Error calculating time decay: {str(e)}")
178 | return 1.0
179 |
180 | def validate_trade(self, portfolio_value, position_size, stop_loss_price, entry_price):
181 | """Comprehensive trade validation with multiple risk checks"""
182 | try:
183 | # Check position size limits
184 | if position_size > portfolio_value * self.max_position_size:
185 | return False, "Position size exceeds maximum allowed"
186 |
187 | # Calculate potential loss
188 | potential_loss = abs(entry_price - stop_loss_price) * position_size / entry_price
189 | if potential_loss > portfolio_value * self.max_drawdown:
190 | return False, "Potential loss exceeds maximum drawdown"
191 |
192 | # Check market state
193 | if self.market_state == 'volatile':
194 | if position_size > portfolio_value * self.max_position_size * 0.7:
195 | return False, "Position size too large for volatile market"
196 |
197 | # Check recent performance
198 | if len(self.drawdown_history) > 0:
199 | recent_drawdown = np.mean(self.drawdown_history[-5:])
200 | if recent_drawdown > self.max_drawdown * 0.8:
201 | return False, "Recent drawdown too high"
202 |
203 | return True, "Trade validated"
204 | except Exception as e:
205 | self.logger.error(f"Error validating trade: {str(e)}")
206 | return False, "Validation error"
207 |
208 | def update_market_state(self, market_data):
209 | """Update market state with new data"""
210 | try:
211 | if not market_data or 'close' not in market_data:
212 | return False
213 |
214 | # Calculate returns
215 | close_prices = market_data['close']
216 | if len(close_prices) < 2:
217 | return False
218 |
219 | returns = np.diff(close_prices) / close_prices[:-1]
220 |
221 | # Update drawdown history
222 | if len(returns) > 0:
223 | drawdown = min(0, returns[-1])
224 | self.drawdown_history.append(drawdown)
225 |
226 | # Keep history length manageable
227 | if len(self.drawdown_history) > 100:
228 | self.drawdown_history = self.drawdown_history[-100:]
229 |
230 | return True
231 | except Exception as e:
232 | self.logger.error(f"Error updating market state: {str(e)}")
233 | return False
234 |
235 | def _check_cumulative_risk(self, potential_loss, portfolio_value, lookback=5):
236 | """Check if recent cumulative risk is too high"""
237 | try:
238 | if len(self.drawdown_history) < lookback:
239 | return False
240 |
241 | recent_drawdowns = self.drawdown_history[-lookback:]
242 | cumulative_risk = sum(recent_drawdowns) + (potential_loss / portfolio_value)
243 |
244 | return cumulative_risk > self.max_drawdown * 2
245 | except Exception as e:
246 | self.logger.error(f"Error checking cumulative risk: {str(e)}")
247 | return True # Conservative approach: reject trade if error
--------------------------------------------------------------------------------
/src/ai_engine/signal_generator.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | from typing import Dict, Optional
4 | import talib
5 | import logging
6 | from .ml_models import MLPredictor
7 |
8 | class SignalGenerator:
9 | def __init__(self):
10 | self.ml_predictor = MLPredictor()
11 | self.logger = logging.getLogger(__name__)
12 |
13 | def calculate_technical_indicators(self, ohlcv_data: pd.DataFrame) -> Dict:
14 | """计算技术指标"""
15 | try:
16 | close = ohlcv_data['close'].values
17 | high = ohlcv_data['high'].values
18 | low = ohlcv_data['low'].values
19 | volume = ohlcv_data['volume'].values
20 |
21 | # 计算移动平均
22 | sma_20 = talib.SMA(close, timeperiod=20)[-1]
23 | sma_50 = talib.SMA(close, timeperiod=50)[-1]
24 | ema_12 = talib.EMA(close, timeperiod=12)[-1]
25 |
26 | # 计算动量指标
27 | rsi = talib.RSI(close, timeperiod=14)[-1]
28 | macd, macd_signal, _ = talib.MACD(close)
29 | macd_value = macd[-1]
30 | macd_signal = macd_signal[-1]
31 |
32 | # 计算波动率
33 | atr = talib.ATR(high, low, close, timeperiod=14)[-1]
34 | volatility = talib.STDDEV(close, timeperiod=20)[-1]
35 |
36 | # 计算成交量指标
37 | obv = talib.OBV(close, volume)[-1]
38 |
39 | return {
40 | 'sma_20': sma_20,
41 | 'sma_50': sma_50,
42 | 'ema_12': ema_12,
43 | 'rsi': rsi,
44 | 'macd': macd_value,
45 | 'macd_signal': macd_signal,
46 | 'atr': atr,
47 | 'volatility': volatility,
48 | 'obv': obv
49 | }
50 | except Exception as e:
51 | self.logger.error(f"Error calculating technical indicators: {str(e)}")
52 | return None
53 |
54 | def generate_signal(self, market_data: Dict, portfolio_value: float) -> Optional[Dict]:
55 | """生成交易信号"""
56 | try:
57 | if market_data is None or 'ohlcv' not in market_data:
58 | return None
59 |
60 | # 计算技术指标
61 | indicators = self.calculate_technical_indicators(market_data['ohlcv'])
62 | if not indicators:
63 | return None
64 |
65 | # 准备ML模型特征
66 | features = self.ml_predictor.prepare_features(indicators)
67 |
68 | # 获取ML模型预测
69 | signal, confidence = self.ml_predictor.predict(features)
70 |
71 | # 计算技术分析信号
72 | ta_signal = self._calculate_ta_signal(indicators)
73 |
74 | # 综合信号
75 | final_signal = self._combine_signals(signal, ta_signal, confidence)
76 |
77 | return {
78 | 'signal': final_signal,
79 | 'confidence': confidence,
80 | 'indicators': indicators,
81 | 'ml_signal': signal,
82 | 'ta_signal': ta_signal,
83 | 'timestamp': market_data['timestamp']
84 | }
85 | except Exception as e:
86 | self.logger.error(f"Error generating signal: {str(e)}")
87 | return None
88 |
89 | def _calculate_ta_signal(self, indicators: Dict) -> int:
90 | """计算技术分析信号"""
91 | signals = []
92 |
93 | # 移动平均趋势
94 | if indicators['sma_20'] > indicators['sma_50']:
95 | signals.append(1)
96 | elif indicators['sma_20'] < indicators['sma_50']:
97 | signals.append(-1)
98 | else:
99 | signals.append(0)
100 |
101 | # RSI信号
102 | if indicators['rsi'] > 70:
103 | signals.append(-1) # 超买
104 | elif indicators['rsi'] < 30:
105 | signals.append(1) # 超卖
106 | else:
107 | signals.append(0)
108 |
109 | # MACD信号
110 | if indicators['macd'] > indicators['macd_signal']:
111 | signals.append(1)
112 | elif indicators['macd'] < indicators['macd_signal']:
113 | signals.append(-1)
114 | else:
115 | signals.append(0)
116 |
117 | # 返回综合信号
118 | return int(np.sign(sum(signals)))
119 |
120 | def _combine_signals(self, ml_signal: int, ta_signal: int, confidence: float) -> int:
121 | """综合ML和技术分析信号"""
122 | # 如果ML置信度高,赋予更大权重
123 | if confidence > 0.8:
124 | return ml_signal
125 | elif confidence > 0.6:
126 | # ML和技术分析信号一致时保持,不一致时偏向ML信号
127 | return ml_signal if ml_signal == ta_signal else int(np.sign(0.7 * ml_signal + 0.3 * ta_signal))
128 | else:
129 | # ML置信度低时偏向技术分析信号
130 | return ta_signal
--------------------------------------------------------------------------------
/src/ai_engine/trading_engine.py:
--------------------------------------------------------------------------------
1 | import ccxt
2 | import numpy as np
3 | from datetime import datetime
4 | import logging
5 | from .ml_models import MLPredictor
6 | from .risk_manager import RiskManager
7 | from .market_data import MarketDataCollector
8 |
9 | class TradingEngine:
10 | def __init__(self, api_key=None, api_secret=None):
11 | # Initialize market data collector
12 | self.market_data = MarketDataCollector(api_key=api_key, api_secret=api_secret)
13 |
14 | # Initialize ML predictor and risk manager
15 | self.ml_predictor = MLPredictor()
16 | self.risk_manager = RiskManager()
17 |
18 | # Configure logging
19 | logging.basicConfig(level=logging.INFO)
20 | self.logger = logging.getLogger(__name__)
21 |
22 | # Trading state
23 | self.active_positions = {}
24 | self.pending_orders = {}
25 |
26 | def fetch_market_data(self, symbol, timeframe='1m', limit=100):
27 | """Fetch comprehensive market data"""
28 | try:
29 | # Fetch OHLCV data
30 | ohlcv_data = self.market_data.fetch_historical_data(symbol, timeframe, limit)
31 | if ohlcv_data is None:
32 | return None
33 |
34 | # Fetch orderbook
35 | orderbook = self.market_data.fetch_orderbook(symbol)
36 |
37 | # Fetch recent trades
38 | trades = self.market_data.fetch_recent_trades(symbol)
39 |
40 | # Calculate VWAP
41 | vwap = self.market_data.calculate_vwap(trades)
42 |
43 | return {
44 | 'ohlcv': ohlcv_data,
45 | 'orderbook': orderbook,
46 | 'vwap': vwap,
47 | 'timestamp': datetime.now().timestamp()
48 | }
49 | except Exception as e:
50 | self.logger.error(f"Error fetching market data: {str(e)}")
51 | return None
52 |
53 | def generate_trading_signal(self, market_data, portfolio_value):
54 | """Generate comprehensive trading signal"""
55 | try:
56 | if market_data is None:
57 | return None
58 |
59 | # Calculate technical indicators
60 | indicators = self.calculate_technical_indicators(market_data['ohlcv'])
61 | if not indicators:
62 | return None
63 |
64 | # Add market microstructure features
65 | if market_data['orderbook']:
66 | trade_size = portfolio_value * 0.01 # 1% of portfolio for impact calculation
67 | impact = self.market_data.calculate_market_impact(market_data['orderbook'], trade_size)
68 | indicators.update({
69 | 'buy_impact': impact['buy_impact'] if impact else None,
70 | 'sell_impact': impact['sell_impact'] if impact else None,
71 | 'vwap': market_data['vwap']
72 | })
73 |
74 | # Prepare features for ML model
75 | features = self.ml_predictor.prepare_features(indicators)
76 |
77 | # Get prediction and confidence
78 | signal, confidence = self.ml_predictor.predict(features)
79 |
80 | # Calculate position size based on risk management
81 | position_size = self.risk_manager.calculate_position_size(
82 | portfolio_value,
83 | indicators['volatility'],
84 | confidence
85 | )
86 |
87 | # Calculate stop loss and take profit levels
88 | current_price = market_data['ohlcv']['close'].iloc[-1]
89 | stop_loss = self.risk_manager.calculate_stop_loss(
90 | current_price,
91 | 'long' if signal > 0 else 'short'
92 | )
93 |
94 | return {
95 | 'signal': signal, # 1 for long, -1 for short, 0 for neutral
96 | 'confidence': confidence,
97 | 'position_size': position_size,
98 | 'stop_loss': stop_loss,
99 | 'indicators': indicators,
100 | 'timestamp': market_data['timestamp']
101 | }
102 | except Exception as e:
103 | self.logger.error(f"Error generating trading signal: {str(e)}")
104 | return None
105 |
106 | def execute_trade(self, symbol, signal):
107 | """Execute trade based on signal"""
108 | try:
109 | if not signal or signal['signal'] == 0:
110 | return False
111 |
112 | # Validate trade with risk manager
113 | trade_valid, reason = self.risk_manager.validate_trade(
114 | portfolio_value=self.get_portfolio_value(),
115 | position_size=signal['position_size'],
116 | stop_loss_price=signal['stop_loss'],
117 | entry_price=signal['indicators']['close'][-1]
118 | )
119 |
120 | if not trade_valid:
121 | self.logger.warning(f"Trade validation failed: {reason}")
122 | return False
123 |
124 | # Place order logic here
125 | order_type = 'market'
126 | side = 'buy' if signal['signal'] > 0 else 'sell'
127 |
128 | self.logger.info(f"Executing {side} order for {symbol} with size {signal['position_size']}")
129 |
130 | # Update position tracking
131 | self.active_positions[symbol] = {
132 | 'side': side,
133 | 'size': signal['position_size'],
134 | 'entry_price': signal['indicators']['close'][-1],
135 | 'stop_loss': signal['stop_loss'],
136 | 'timestamp': signal['timestamp']
137 | }
138 |
139 | return True
140 | except Exception as e:
141 | self.logger.error(f"Error executing trade: {str(e)}")
142 | return False
143 |
144 | def get_portfolio_value(self):
145 | """Get current portfolio value"""
146 | # Implement portfolio value calculation
147 | return 10000 # Placeholder value
148 |
149 | def calculate_technical_indicators(self, market_data):
150 | """Calculate technical indicators for trading decisions"""
151 | if not market_data:
152 | return None
153 |
154 | close_prices = market_data['close']
155 | high_prices = market_data['high']
156 | low_prices = market_data['low']
157 |
158 | # Calculate SMA
159 | sma_20 = np.mean(close_prices[-20:]) if len(close_prices) >= 20 else None
160 | sma_50 = np.mean(close_prices[-50:]) if len(close_prices) >= 50 else None
161 |
162 | # Calculate RSI
163 | delta = np.diff(close_prices)
164 | gain = (delta > 0) * delta
165 | loss = (delta < 0) * -delta
166 | avg_gain = np.mean(gain[-14:]) if len(gain) >= 14 else None
167 | avg_loss = np.mean(loss[-14:]) if len(loss) >= 14 else None
168 |
169 | if avg_gain is not None and avg_loss is not None and avg_loss != 0:
170 | rs = avg_gain / avg_loss
171 | rsi = 100 - (100 / (1 + rs))
172 | else:
173 | rsi = None
174 |
175 | # Calculate volatility
176 | volatility = np.std(np.diff(np.log(close_prices[-20:]))) if len(close_prices) >= 20 else None
177 |
178 | return {
179 | 'sma_20': sma_20,
180 | 'sma_50': sma_50,
181 | 'rsi': rsi,
182 | 'volatility': volatility
183 | }
184 |
185 | def generate_trading_signal(self, market_data):
186 | """Generate trading signal based on market data and ML predictions"""
187 | try:
188 | # Calculate technical indicators
189 | indicators = self.calculate_technical_indicators(market_data)
190 | if not indicators:
191 | return None
192 |
193 | # Prepare features for ML model
194 | features = self.ml_predictor.prepare_features(indicators)
195 |
196 | # Get prediction and confidence
197 | signal, confidence = self.ml_predictor.predict(features)
198 |
199 | # Calculate position size based on risk management
200 | position_size = self.risk_manager.calculate_position_size(
201 | portfolio_value=100000, # Default portfolio value
202 | volatility=indicators['volatility'],
203 | risk_score=confidence
204 | )
205 |
206 | # Generate final trading signal
207 | if signal != 0 and position_size > 0:
208 | stop_loss = self.risk_manager.calculate_stop_loss(
209 | entry_price=market_data['close'][-1],
210 | position_type='long' if signal > 0 else 'short'
211 | )
212 |
213 | return {
214 | 'symbol': market_data.get('symbol'),
215 | 'signal': signal, # 1 for long, -1 for short, 0 for neutral
216 | 'confidence': confidence,
217 | 'position_size': position_size,
218 | 'stop_loss': stop_loss,
219 | 'indicators': indicators,
220 | 'timestamp': datetime.now().timestamp()
221 | }
222 |
223 | return None
224 | except Exception as e:
225 | self.logger.error(f"Error generating trading signal: {str(e)}")
226 | return None
227 |
228 | def validate_signal(self, signal_data):
229 | """Validate trading signal with risk management rules"""
230 | if not signal_data:
231 | return False
232 |
233 | try:
234 | # Validate trade with risk manager
235 | is_valid, reason = self.risk_manager.validate_trade(
236 | portfolio_value=100000, # Default portfolio value
237 | position_size=signal_data['position_size'],
238 | stop_loss_price=signal_data['stop_loss'],
239 | entry_price=signal_data['indicators']['close'][-1]
240 | )
241 |
242 | if not is_valid:
243 | self.logger.warning(f"Trade validation failed: {reason}")
244 | return False
245 |
246 | return True
247 | except Exception as e:
248 | self.logger.error(f"Error validating signal: {str(e)}")
249 | return False
250 |
251 | def update_market_state(self, market_data):
252 | """Update internal market state with new data"""
253 | try:
254 | # Update risk manager with new market data
255 | self.risk_manager.update_market_state(market_data)
256 |
257 | # Update ML model features
258 | self.ml_predictor.update_features(market_data)
259 |
260 | return True
261 | except Exception as e:
262 | self.logger.error(f"Error updating market state: {str(e)}")
263 | return False
264 |
265 | return {
266 | 'sma_20': sma_20,
267 | 'sma_50': sma_50,
268 | 'rsi': rsi
269 | }
270 | return None
271 |
272 | def generate_trading_signal(self, market_data):
273 | """Generate trading signals based on market data and technical analysis
274 |
275 | Args:
276 | market_data (dict): Processed market data
277 |
278 | Returns:
279 | dict: Trading signal with direction and confidence
280 | """
281 | if not market_data:
282 | return None
283 |
284 | # Calculate technical indicators
285 | indicators = self.calculate_technical_indicators(market_data)
286 | if not indicators:
287 | return None
288 |
289 | # Get ML prediction
290 | features = self.ml_predictor.prepare_features(indicators)
291 | prediction = self.ml_predictor.predict(features)
292 |
293 | # Calculate volatility
294 | close_prices = market_data['close']
295 | returns = np.diff(close_prices) / close_prices[:-1]
296 | volatility = np.std(returns)
297 |
298 | # Generate signal
299 | signal = {
300 | 'timestamp': datetime.now().timestamp(),
301 | 'symbol': market_data.get('symbol'),
302 | 'direction': 'buy' if prediction == 1 else 'sell' if prediction == -1 else None,
303 | 'confidence': abs(prediction),
304 | 'volatility': volatility,
305 | 'indicators': indicators
306 | }
307 |
308 | # Validate signal with risk management
309 | if signal['direction']:
310 | portfolio_value = self.get_portfolio_value()
311 | position_size = self.risk_manager.calculate_position_size(
312 | portfolio_value,
313 | volatility,
314 | signal['confidence']
315 | )
316 |
317 | current_price = close_prices[-1]
318 | stop_loss = self.risk_manager.calculate_stop_loss(
319 | current_price,
320 | 'long' if signal['direction'] == 'buy' else 'short'
321 | )
322 |
323 | is_valid, reason = self.risk_manager.validate_trade(
324 | portfolio_value,
325 | position_size,
326 | stop_loss,
327 | current_price
328 | )
329 |
330 | if not is_valid:
331 | self.logger.warning(f"Trade validation failed: {reason}")
332 | return None
333 |
334 | signal['position_size'] = position_size
335 | signal['stop_loss'] = stop_loss
336 |
337 | return signal if signal['direction'] else None
338 |
339 | def get_portfolio_value(self):
340 | """Get current portfolio value
341 |
342 | Returns:
343 | float: Total portfolio value in USDT
344 | """
345 | try:
346 | balance = self.exchange.fetch_balance()
347 | return float(balance['total']['USDT'])
348 | except Exception as e:
349 | self.logger.error(f"Error fetching portfolio value: {str(e)}")
350 | return 0.0
351 | # Trading logic based on multiple indicators
352 | close_prices = market_data['close']
353 | current_price = close_prices[-1]
354 |
355 | # Trend following strategy
356 | trend_signal = 'long' if indicators['sma_20'] > indicators['sma_50'] else 'short'
357 |
358 | # RSI strategy
359 | rsi_signal = None
360 | if indicators['rsi'] is not None:
361 | if indicators['rsi'] < 30:
362 | rsi_signal = 'long' # Oversold
363 | elif indicators['rsi'] > 70:
364 | rsi_signal = 'short' # Overbought
365 |
366 | # Combine signals
367 | final_direction = trend_signal
368 | if rsi_signal and rsi_signal != trend_signal:
369 | # If RSI contradicts trend, reduce confidence
370 | confidence = 0.5
371 | else:
372 | confidence = 0.8
373 |
374 | signal = {
375 | 'timestamp': datetime.now().timestamp(),
376 | 'direction': final_direction,
377 | 'confidence': confidence,
378 | 'price': current_price,
379 | 'indicators': indicators
380 | }
381 |
382 | self.logger.info(f"Generated trading signal: {signal}")
383 | return signal
--------------------------------------------------------------------------------
/src/ai_engine/voice_generator.py:
--------------------------------------------------------------------------------
1 | import os
2 | import torch
3 | import logging
4 | from transformers import pipeline
5 | from TTS.api import TTS
6 |
7 | class VoiceGenerator:
8 | def __init__(self, config):
9 | self.config = config
10 | self.text_generator = pipeline('text-generation')
11 | self.tts = TTS(config.voice.tts.model, gpu=torch.cuda.is_available())
12 | self.languages = {
13 | 'en': 'English',
14 | 'zh': 'Chinese',
15 | 'ja': 'Japanese',
16 | 'ko': 'Korean',
17 | 'ru': 'Russian'
18 | }
19 |
20 | # 设置日志记录
21 | logging.basicConfig(level=logging.INFO)
22 | self.logger = logging.getLogger(__name__)
23 |
24 | def generate_confession_text(self, trade_data, language='en'):
25 | """根据交易数据生成认罪文本"""
26 | templates = {
27 | 'en': [
28 | "I confess that I FOMOed into {symbol} at {price}. I should have done more research. 😔",
29 | "I admit that I leveraged too much on {symbol} and lost {loss}. I was too greedy. 😭",
30 | "I acknowledge my mistake of not setting stop losses on {symbol}. It was pure gambling. 🎰",
31 | "I got rekt on {symbol} because I followed some random influencer. Never again! 🤦",
32 | "My portfolio is down {loss} because I aped into {symbol}. I'm such a degen. 🦍"
33 | ],
34 | 'zh': [
35 | "我承认我在{price}的价格追高了{symbol}。我应该做更多研究的。😔",
36 | "我承认我在{symbol}上使用了过高的杠杆,亏损了{loss}。我太贪心了。😭",
37 | "我承认我没有在{symbol}上设置止损。这完全是在赌博。🎰",
38 | "我因为跟随某个网红买入{symbol}结果被割了。以后再也不会这样了!🤦",
39 | "我的投资组合因为冲动买入{symbol}已经亏损{loss}了。我就是个韭菜。🦍"
40 | ],
41 | 'ja': [
42 | "{symbol}を{price}で追いかけ買いしてしまいました。もっと調査すべきでした。😔",
43 | "{symbol}で過度なレバレッジを使い、{loss}を失いました。欲が深すぎました。😭",
44 | "{symbol}でストップロスを設定しませんでした。ただの賭け事でした。🎰",
45 | "インフルエンサーに従って{symbol}を買って失敗しました。もう二度としません!🤦",
46 | "{symbol}に飛び込んで{loss}損失しました。私は本当にバカでした。🦍"
47 | ]
48 | }
49 |
50 | template = torch.randint(0, len(templates[language]), (1,)).item()
51 | text = templates[language][template].format(
52 | symbol=trade_data['symbol'],
53 | price=trade_data.get('price', '0'),
54 | loss=trade_data.get('loss', '0')
55 | )
56 | return text
57 |
58 | def generate_voice(self, text, language='en', speaker_name="default", output_path=None, emotion="neutral"):
59 | """生成语音文件
60 | Args:
61 | text: 要转换的文本
62 | language: 语言代码 ('en', 'zh', 'ja', 'ko', 'ru')
63 | speaker_name: 说话人名称
64 | output_path: 输出文件路径
65 | emotion: 情感类型 ('neutral', 'sad', 'happy', 'angry', 'excited', 'depressed')
66 | Returns:
67 | 生成的语音文件路径
68 | """
69 | try:
70 | # 根据情感调整语音参数
71 | emotion_params = {
72 | 'neutral': {'speed': 1.0, 'pitch': 1.0, 'energy': 1.0},
73 | 'sad': {'speed': 0.8, 'pitch': 0.8, 'energy': 0.7},
74 | 'happy': {'speed': 1.2, 'pitch': 1.2, 'energy': 1.3},
75 | 'angry': {'speed': 1.3, 'pitch': 1.4, 'energy': 1.5},
76 | 'excited': {'speed': 1.4, 'pitch': 1.3, 'energy': 1.6},
77 | 'depressed': {'speed': 0.7, 'pitch': 0.7, 'energy': 0.5}
78 | }
79 |
80 | params = emotion_params.get(emotion, emotion_params['neutral'])
81 |
82 | # 如果没有指定输出路径,使用临时文件
83 | if not output_path:
84 | output_path = os.path.join(
85 | os.path.dirname(__file__),
86 | 'generated_voices',
87 | f'confession_{language}_{emotion}_{speaker_name}_{hash(text)}.wav'
88 | )
89 |
90 | os.makedirs(os.path.dirname(output_path), exist_ok=True)
91 |
92 | # 生成语音
93 | self.tts.tts_to_file(
94 | text=text,
95 | file_path=output_path,
96 | speaker_name=speaker_name,
97 | language=self.languages[language],
98 | speed=params['speed'],
99 | pitch=params['pitch'],
100 | energy=params['energy']
101 | )
102 |
103 | self.logger.info(f"Successfully generated voice file: {output_path}")
104 | return output_path
105 |
106 | except Exception as e:
107 | self.logger.error(f"Error generating voice: {str(e)}")
108 | raise e
109 |
110 | def generate_trade_confession(self, trade_data, language='en', speaker_name="default", emotion="sad"):
111 | """生成交易认罪语音"""
112 | # 生成认罪文本
113 | confession_text = self.generate_confession_text(trade_data, language)
114 |
115 | # 生成语音文件
116 | voice_path = self.generate_voice(
117 | confession_text,
118 | language,
119 | speaker_name,
120 | emotion=emotion
121 | )
122 |
123 | return {
124 | 'text': confession_text,
125 | 'voice_path': voice_path,
126 | 'language': language,
127 | 'emotion': emotion
128 | }
--------------------------------------------------------------------------------
/src/config/ai_social_config.js:
--------------------------------------------------------------------------------
1 | const aiSocialConfig = {
2 | // 语音生成配置
3 | voice: {
4 | // TTS模型配置
5 | tts: {
6 | model: "tts_models/multilingual/multi-dataset/your_tts",
7 | defaultSpeaker: "default",
8 | outputDir: "generated_voices"
9 | },
10 | // 语音模板配置
11 | templates: {
12 | confession: {
13 | en: [
14 | "I confess that I FOMOed into {symbol} at {price}. I should have done more research.",
15 | "I admit that I leveraged too much on {symbol} and lost {loss}. I was too greedy.",
16 | "I acknowledge my mistake of not setting stop losses on {symbol}. It was pure gambling."
17 | ],
18 | zh: [
19 | "我承认我在{price}的价格追高了{symbol}。我应该做更多研究的。",
20 | "我承认我在{symbol}上使用了过高的杠杆,亏损了{loss}。我太贪心了。",
21 | "我承认我没有在{symbol}上设置止损。这完全是在赌博。"
22 | ],
23 | ja: [
24 | "{symbol}を{price}で追いかけ買いしてしまいました。もっと調査すべきでした。",
25 | "{symbol}で過度なレバレッジを使い、{loss}を失いました。欲が深すぎました。",
26 | "{symbol}でストップロスを設定しませんでした。ただの賭け事でした。"
27 | ]
28 | }
29 | }
30 | },
31 |
32 | // 社交媒体配置
33 | social: {
34 | // 发布平台配置
35 | platforms: {
36 | twitter: {
37 | enabled: true,
38 | apiVersion: "2.0",
39 | rateLimit: 300, // 5分钟内的请求限制
40 | mediaSupport: true
41 | },
42 | telegram: {
43 | enabled: true,
44 | mediaSupport: true,
45 | maxMessageLength: 4096
46 | },
47 | discord: {
48 | enabled: true,
49 | mediaSupport: true,
50 | maxFileSize: 8388608 // 8MB
51 | }
52 | },
53 |
54 | // 内容发布策略
55 | postingStrategy: {
56 | retryAttempts: 3,
57 | retryDelay: 1000, // 毫秒
58 | priorityOrder: ["twitter", "telegram", "discord"],
59 | batchSize: 5 // 批量发布数量
60 | },
61 |
62 | // 内容模板
63 | templates: {
64 | tradeAlert: "🚨 Trade Alert! {symbol}\nPrice: {price}\nPosition: {position}\nLeverage: {leverage}x",
65 | confession: "😅 Trading Confession\n{text}\n#tradingconfession #{symbol}",
66 | meme: "🎭 {symbol} Trading Meme\n{caption}\n#tradingmeme #{symbol}"
67 | }
68 | }
69 | };
70 |
71 | module.exports = aiSocialConfig;
--------------------------------------------------------------------------------
/src/contracts/abi.js:
--------------------------------------------------------------------------------
1 | const FollowTradeABI = [
2 | {
3 | "inputs": [
4 | {
5 | "internalType": "uint256",
6 | "name": "_followFee",
7 | "type": "uint256"
8 | },
9 | {
10 | "internalType": "uint256",
11 | "name": "_burnRate",
12 | "type": "uint256"
13 | }
14 | ],
15 | "stateMutability": "nonpayable",
16 | "type": "constructor"
17 | },
18 | {
19 | "anonymous": false,
20 | "inputs": [
21 | {
22 | "indexed": false,
23 | "internalType": "address",
24 | "name": "follower",
25 | "type": "address"
26 | },
27 | {
28 | "indexed": false,
29 | "internalType": "string",
30 | "name": "symbol",
31 | "type": "string"
32 | },
33 | {
34 | "indexed": false,
35 | "internalType": "uint256",
36 | "name": "fee",
37 | "type": "uint256"
38 | }
39 | ],
40 | "name": "FollowTradeStarted",
41 | "type": "event"
42 | },
43 | {
44 | "anonymous": false,
45 | "inputs": [
46 | {
47 | "indexed": false,
48 | "internalType": "address",
49 | "name": "trader",
50 | "type": "address"
51 | },
52 | {
53 | "indexed": false,
54 | "internalType": "address",
55 | "name": "follower",
56 | "type": "address"
57 | },
58 | {
59 | "indexed": false,
60 | "internalType": "uint256",
61 | "name": "amount",
62 | "type": "uint256"
63 | }
64 | ],
65 | "name": "ProfitDistributed",
66 | "type": "event"
67 | },
68 | {
69 | "anonymous": false,
70 | "inputs": [
71 | {
72 | "indexed": false,
73 | "internalType": "uint256",
74 | "name": "amount",
75 | "type": "uint256"
76 | }
77 | ],
78 | "name": "TokensBurned",
79 | "type": "event"
80 | },
81 | {
82 | "anonymous": false,
83 | "inputs": [
84 | {
85 | "indexed": false,
86 | "internalType": "address",
87 | "name": "user",
88 | "type": "address"
89 | },
90 | {
91 | "indexed": false,
92 | "internalType": "uint256",
93 | "name": "amount",
94 | "type": "uint256"
95 | }
96 | ],
97 | "name": "RewardsWithdrawn",
98 | "type": "event"
99 | },
100 | {
101 | "inputs": [
102 | {
103 | "internalType": "address",
104 | "name": "",
105 | "type": "address"
106 | },
107 | {
108 | "internalType": "string",
109 | "name": "",
110 | "type": "string"
111 | }
112 | ],
113 | "name": "activeFollows",
114 | "outputs": [
115 | {
116 | "internalType": "bool",
117 | "name": "",
118 | "type": "bool"
119 | }
120 | ],
121 | "stateMutability": "view",
122 | "type": "function"
123 | },
124 | {
125 | "inputs": [
126 | {
127 | "internalType": "address[]",
128 | "name": "followers",
129 | "type": "address[]"
130 | },
131 | {
132 | "internalType": "uint256[]",
133 | "name": "amounts",
134 | "type": "uint256[]"
135 | }
136 | ],
137 | "name": "distributeProfits",
138 | "outputs": [],
139 | "stateMutability": "nonpayable",
140 | "type": "function"
141 | },
142 | {
143 | "inputs": [
144 | {
145 | "internalType": "string",
146 | "name": "symbol",
147 | "type": "string"
148 | }
149 | ],
150 | "name": "startFollow",
151 | "outputs": [],
152 | "stateMutability": "payable",
153 | "type": "function"
154 | },
155 | {
156 | "inputs": [
157 | {
158 | "internalType": "uint256",
159 | "name": "_newRate",
160 | "type": "uint256"
161 | }
162 | ],
163 | "name": "updateBurnRate",
164 | "outputs": [],
165 | "stateMutability": "nonpayable",
166 | "type": "function"
167 | },
168 | {
169 | "inputs": [
170 | {
171 | "internalType": "uint256",
172 | "name": "_newFee",
173 | "type": "uint256"
174 | }
175 | ],
176 | "name": "updateFollowFee",
177 | "outputs": [],
178 | "stateMutability": "nonpayable",
179 | "type": "function"
180 | },
181 | {
182 | "inputs": [],
183 | "name": "withdraw",
184 | "outputs": [],
185 | "stateMutability": "nonpayable",
186 | "type": "function"
187 | },
188 | {
189 | "inputs": [],
190 | "name": "withdrawRewards",
191 | "outputs": [],
192 | "stateMutability": "nonpayable",
193 | "type": "function"
194 | }
195 | ];
196 |
197 | module.exports = { FollowTradeABI };
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 | const app = express();
3 | const http = require('http').createServer(app);
4 | const io = require('socket.io')(http);
5 | const dotenv = require('dotenv');
6 | const TradingService = require('./services/trading_service');
7 |
8 | dotenv.config();
9 |
10 | // Initialize trading service
11 | const tradingService = new TradingService(
12 | process.env.SOLANA_ENDPOINT || 'https://api.devnet.solana.com',
13 | process.env.PROGRAM_ID
14 | );
15 |
16 | // Middleware configuration
17 | app.use(express.json());
18 |
19 | // Start trading stream
20 | tradingService.startTradingStream();
21 |
22 | // WebSocket connection handling
23 | io.on('connection', (socket) => {
24 | console.log('User connected');
25 |
26 | socket.on('disconnect', () => {
27 | console.log('User disconnected');
28 | });
29 | });
30 |
31 | // API routes
32 | app.get('/api/health', (req, res) => {
33 | res.json({ status: 'ok' });
34 | });
35 |
36 | // Start server
37 | const PORT = process.env.PORT || 3000;
38 | http.listen(PORT, () => {
39 | console.log(`Server running on port ${PORT}`);
40 | });
--------------------------------------------------------------------------------
/src/services/follow_trade_service.js:
--------------------------------------------------------------------------------
1 | const { Connection, PublicKey, Transaction, SystemProgram } = require('@solana/web3.js');
2 | const BN = require('bn.js');
3 | const { Program } = require('@project-serum/anchor');
4 | const WebSocket = require('ws');
5 |
6 | class FollowTradeService {
7 | constructor(endpoint, programId) {
8 | this.connection = new Connection(endpoint);
9 | this.programId = new PublicKey(programId);
10 |
11 | // Initialize WebSocket server for real-time updates
12 | this.wss = new WebSocket.Server({ port: 8081 });
13 | this.followers = new Map();
14 |
15 | this.setupWebSocket();
16 | }
17 |
18 | setupWebSocket() {
19 | this.wss.on('connection', (ws) => {
20 | ws.on('message', async (message) => {
21 | try {
22 | const data = JSON.parse(message);
23 |
24 | switch (data.type) {
25 | case 'follow_request':
26 | await this.handleFollowRequest(ws, data);
27 | break;
28 | case 'unfollow_request':
29 | await this.handleUnfollowRequest(ws, data);
30 | break;
31 | }
32 | } catch (error) {
33 | console.error('Error processing WebSocket message:', error);
34 | ws.send(JSON.stringify({
35 | type: 'error',
36 | message: error.message
37 | }));
38 | }
39 | });
40 |
41 | ws.on('close', () => {
42 | this.removeFollower(ws);
43 | });
44 | });
45 | }
46 |
47 | async handleFollowRequest(ws, data) {
48 | const { trader, symbol, publicKey } = data;
49 |
50 | try {
51 | // Create follow instruction
52 | const instruction = await this.program.instruction.startFollow(
53 | symbol,
54 | {
55 | accounts: {
56 | follower: new PublicKey(publicKey),
57 | trader: new PublicKey(trader),
58 | systemProgram: SystemProgram.programId,
59 | },
60 | }
61 | );
62 |
63 | // Add to followers list
64 | this.followers.set(ws, {
65 | publicKey,
66 | trader,
67 | symbol
68 | });
69 |
70 | // Send confirmation
71 | ws.send(JSON.stringify({
72 | type: 'follow_success',
73 | trader,
74 | symbol
75 | }));
76 | } catch (error) {
77 | ws.send(JSON.stringify({
78 | type: 'error',
79 | message: 'Failed to start following: ' + error.message
80 | }));
81 | }
82 | }
83 |
84 | async handleUnfollowRequest(ws, data) {
85 | const follower = this.followers.get(ws);
86 | if (!follower) {
87 | return;
88 | }
89 |
90 | try {
91 | // Remove from followers list
92 | this.followers.delete(ws);
93 |
94 | // Send confirmation
95 | ws.send(JSON.stringify({
96 | type: 'unfollow_success',
97 | trader: follower.trader,
98 | symbol: follower.symbol
99 | }));
100 | } catch (error) {
101 | ws.send(JSON.stringify({
102 | type: 'error',
103 | message: 'Failed to unfollow: ' + error.message
104 | }));
105 | }
106 | }
107 |
108 | removeFollower(ws) {
109 | this.followers.delete(ws);
110 | }
111 |
112 | broadcastTradeSignal(trader, symbol, signal) {
113 | this.followers.forEach((follower, ws) => {
114 | if (follower.trader === trader &&
115 | follower.symbol === symbol &&
116 | ws.readyState === WebSocket.OPEN) {
117 | ws.send(JSON.stringify({
118 | type: 'trade_signal',
119 | trader,
120 | symbol,
121 | signal
122 | }));
123 | }
124 | });
125 | }
126 |
127 | async distributeProfits(trader, symbol, profits) {
128 | const followers = Array.from(this.followers.values())
129 | .filter(f => f.trader === trader && f.symbol === symbol);
130 |
131 | if (followers.length === 0) {
132 | return;
133 | }
134 |
135 | try {
136 | // Calculate profit shares
137 | const traderShare = (profits * 70) / 100; // 70% to trader
138 | const followerShare = (profits * 30) / followers.length; // 30% split among followers
139 |
140 | // Create profit distribution instruction
141 | const instruction = await this.program.instruction.distributeProfit(
142 | new BN(profits),
143 | {
144 | accounts: {
145 | trader: new PublicKey(trader),
146 | // Add other required accounts
147 | },
148 | }
149 | );
150 |
151 | // Broadcast profit distribution
152 | followers.forEach(({ publicKey }, ws) => {
153 | if (ws.readyState === WebSocket.OPEN) {
154 | ws.send(JSON.stringify({
155 | type: 'profit_distribution',
156 | trader,
157 | symbol,
158 | amount: followerShare
159 | }));
160 | }
161 | });
162 | } catch (error) {
163 | console.error('Error distributing profits:', error);
164 | }
165 | }
166 | }
167 |
168 | module.exports = FollowTradeService;
--------------------------------------------------------------------------------
/src/services/real_time_processor.js:
--------------------------------------------------------------------------------
1 | const WebSocket = require('ws');
2 | const { MarketDataCollector } = require('../ai_engine/market_data');
3 | const { SignalGenerator } = require('../ai_engine/signal_generator');
4 | const { RiskManager } = require('../ai_engine/risk_manager');
5 | const { ethers } = require('ethers');
6 | const followTradeABI = require('../contracts/abi');
7 |
8 | class RealTimeProcessor {
9 | constructor(config) {
10 | this.marketData = new MarketDataCollector(config.exchange);
11 | this.signalGenerator = new SignalGenerator();
12 | this.riskManager = new RiskManager();
13 | this.subscribers = new Map();
14 | this.activeSymbols = new Set();
15 |
16 | // Initialize smart contract connection
17 | this.provider = new ethers.providers.JsonRpcProvider(config.rpcUrl);
18 | this.wallet = new ethers.Wallet(config.privateKey, this.provider);
19 | this.followTradeContract = new ethers.Contract(
20 | config.contractAddress,
21 | followTradeABI,
22 | this.wallet
23 | );
24 | }
25 |
26 | async start() {
27 | this.wss = new WebSocket.Server({ port: 8082 });
28 | this.setupWebSocket();
29 | this.startDataProcessing();
30 | this.setupContractListeners();
31 | }
32 |
33 | setupWebSocket() {
34 | this.wss.on('connection', (ws) => {
35 | ws.on('message', async (message) => {
36 | try {
37 | const data = JSON.parse(message);
38 | await this.handleMessage(ws, data);
39 | } catch (error) {
40 | console.error('Error processing message:', error);
41 | ws.send(JSON.stringify({ type: 'error', message: error.message }));
42 | }
43 | });
44 |
45 | ws.on('close', () => {
46 | this.removeSubscriber(ws);
47 | });
48 | });
49 | }
50 |
51 | setupContractListeners() {
52 | // Listen for follow trade events
53 | this.followTradeContract.on('FollowTradeStarted', async (follower, symbol, fee) => {
54 | console.log(`New follow trade: ${follower} following ${symbol}`);
55 | await this.handleNewFollower(follower, symbol);
56 | });
57 |
58 | // Listen for profit distribution events
59 | this.followTradeContract.on('ProfitDistributed', (trader, follower, amount) => {
60 | console.log(`Profit distributed: ${amount} to ${follower} from ${trader}`);
61 | });
62 | }
63 |
64 | async handleNewFollower(follower, symbol) {
65 | try {
66 | // Add to active symbols if not already tracking
67 | if (!this.activeSymbols.has(symbol)) {
68 | this.activeSymbols.add(symbol);
69 | await this.startSymbolProcessing(symbol);
70 | }
71 |
72 | // Initialize risk parameters for the follower
73 | const riskMetrics = this.riskManager.get_risk_metrics();
74 | const initialRiskScore = 0.5; // Default risk score
75 |
76 | // Store follower information
77 | if (!this.subscribers.has(symbol)) {
78 | this.subscribers.set(symbol, new Map());
79 | }
80 | this.subscribers.get(symbol).set(follower, {
81 | riskScore: initialRiskScore,
82 | metrics: riskMetrics
83 | });
84 | } catch (error) {
85 | console.error(`Error handling new follower: ${error.message}`);
86 | }
87 | }
88 |
89 | async startSymbolProcessing(symbol) {
90 | try {
91 | while (this.activeSymbols.has(symbol)) {
92 | const marketData = await this.marketData.fetch_historical_data(symbol, '1m', 100);
93 | if (!marketData) continue;
94 |
95 | const technicalIndicators = this.signalGenerator.calculate_technical_indicators(marketData);
96 | const prediction = await this.signalGenerator.generate_signal(technicalIndicators);
97 |
98 | if (prediction) {
99 | await this.processTradeSignal(symbol, prediction, technicalIndicators);
100 | }
101 |
102 | await new Promise(resolve => setTimeout(resolve, 60000)); // 1-minute interval
103 | }
104 | } catch (error) {
105 | console.error(`Error processing symbol ${symbol}: ${error.message}`);
106 | }
107 | }
108 |
109 | async processTradeSignal(symbol, prediction, indicators) {
110 | const subscribers = this.subscribers.get(symbol);
111 | if (!subscribers) return;
112 |
113 | for (const [follower, data] of subscribers) {
114 | try {
115 | // Calculate position size based on risk profile
116 | const positionSize = this.riskManager.calculate_position_size(
117 | 1000, // Default portfolio value, should be fetched from contract
118 | indicators.volatility,
119 | data.riskScore
120 | );
121 |
122 | // Generate trade parameters
123 | const tradeParams = {
124 | symbol,
125 | direction: prediction.signal > 0 ? 'long' : 'short',
126 | size: positionSize,
127 | stopLoss: this.riskManager.calculate_stop_loss(
128 | indicators.close,
129 | prediction.signal > 0 ? 'long' : 'short',
130 | indicators.volatility
131 | )
132 | };
133 |
134 | // Broadcast trade signal to follower
135 | this.broadcastTradeSignal(follower, tradeParams);
136 | } catch (error) {
137 | console.error(`Error processing trade signal for ${follower}: ${error.message}`);
138 | }
139 | }
140 | }
141 |
142 | broadcastTradeSignal(follower, tradeParams) {
143 | const message = {
144 | type: 'trade_signal',
145 | data: tradeParams,
146 | timestamp: Date.now()
147 | };
148 |
149 | // Send signal to specific follower's WebSocket connection
150 | const ws = Array.from(this.wss.clients).find(client =>
151 | client.follower === follower && client.readyState === WebSocket.OPEN
152 | );
153 |
154 | if (ws) {
155 | ws.send(JSON.stringify(message));
156 | }
157 | }
158 | }
159 |
160 | module.exports = RealTimeProcessor;
--------------------------------------------------------------------------------
/src/services/real_time_service.js:
--------------------------------------------------------------------------------
1 | const { WebSocketServer } = require('ws');
2 | const { TradingEngine } = require('../ai_engine/trading_engine');
3 | const { ethers } = require('ethers');
4 | const followTradeABI = require('../contracts/FollowTrade.json');
5 |
6 | class RealTimeService {
7 | constructor(config) {
8 | this.tradingEngine = new TradingEngine(config.apiKey, config.apiSecret);
9 | this.provider = new ethers.providers.JsonRpcProvider(config.rpcUrl);
10 | this.wallet = new ethers.Wallet(config.privateKey, this.provider);
11 | this.followTradeContract = new ethers.Contract(
12 | config.contractAddress,
13 | followTradeABI,
14 | this.wallet
15 | );
16 |
17 | this.wss = new WebSocketServer({ port: config.wsPort });
18 | this.activeSymbols = new Set();
19 | this.subscribers = new Map();
20 | this.initialize();
21 | }
22 |
23 | initialize() {
24 | // 设置WebSocket连接处理
25 | this.wss.on('connection', (ws) => {
26 | ws.on('message', async (message) => {
27 | try {
28 | const data = JSON.parse(message);
29 | switch(data.type) {
30 | case 'subscribe':
31 | await this.handleSubscribe(ws, data);
32 | break;
33 | case 'unsubscribe':
34 | await this.handleUnsubscribe(ws, data);
35 | break;
36 | }
37 | } catch (error) {
38 | console.error('Error processing message:', error);
39 | ws.send(JSON.stringify({ type: 'error', message: error.message }));
40 | }
41 | });
42 | });
43 |
44 | // 启动信号生成循环
45 | this.startSignalGeneration();
46 | }
47 |
48 | async handleSubscribe(ws, data) {
49 | const { symbol, address } = data;
50 |
51 | // 验证用户是否有效跟随者
52 | const isActiveFollower = await this.followTradeContract.getFollowerStatus(address, symbol);
53 | if (!isActiveFollower) {
54 | ws.send(JSON.stringify({
55 | type: 'error',
56 | message: 'Not an active follower for this symbol'
57 | }));
58 | return;
59 | }
60 |
61 | // 添加到订阅列表
62 | if (!this.subscribers.has(symbol)) {
63 | this.subscribers.set(symbol, new Set());
64 | }
65 | this.subscribers.get(symbol).add(ws);
66 | this.activeSymbols.add(symbol);
67 |
68 | ws.send(JSON.stringify({
69 | type: 'subscribed',
70 | symbol: symbol
71 | }));
72 | }
73 |
74 | async handleUnsubscribe(ws, data) {
75 | const { symbol } = data;
76 | if (this.subscribers.has(symbol)) {
77 | this.subscribers.get(symbol).delete(ws);
78 | if (this.subscribers.get(symbol).size === 0) {
79 | this.subscribers.delete(symbol);
80 | this.activeSymbols.delete(symbol);
81 | }
82 | }
83 | }
84 |
85 | async startSignalGeneration() {
86 | const INTERVAL = 1000; // 1秒更新间隔
87 | const MAX_RETRIES = 3;
88 | let performanceMetrics = new Map();
89 |
90 | setInterval(async () => {
91 | for (const symbol of this.activeSymbols) {
92 | try {
93 | const startTime = Date.now();
94 | let retries = 0;
95 | let marketData;
96 |
97 | // 带重试的市场数据获取
98 | while (retries < MAX_RETRIES && !marketData) {
99 | marketData = await this.tradingEngine.fetch_market_data(symbol);
100 | if (!marketData) {
101 | retries++;
102 | await new Promise(resolve => setTimeout(resolve, 1000 * retries));
103 | }
104 | }
105 |
106 | if (!marketData) {
107 | throw new Error(`Failed to fetch market data for ${symbol} after ${MAX_RETRIES} retries`);
108 | }
109 |
110 | // 获取投资组合价值
111 | const portfolioValue = await this.getPortfolioValue(symbol);
112 |
113 | // 生成交易信号
114 | const signal = await this.tradingEngine.generate_trading_signal(
115 | marketData,
116 | portfolioValue
117 | );
118 |
119 | // 评估交易风险
120 | const riskAssessment = await this.assessTradeRisk(signal, marketData);
121 |
122 | // 记录性能指标
123 | const processingTime = Date.now() - startTime;
124 | this.updatePerformanceMetrics(symbol, processingTime);
125 |
126 | // 广播信号
127 | if (signal && signal.signal !== 0 && signal.confidence > 0.7 && riskAssessment.riskScore < 0.8) {
128 | signal.position_size = riskAssessment.recommendedSize;
129 | await this.broadcastSignal(symbol, signal);
130 | }
131 |
132 | } catch (error) {
133 | console.error(`Error processing ${symbol}:`, error);
134 | this.notifyError(symbol, error);
135 | }
136 | }
137 | }, INTERVAL);
138 | }
139 |
140 | async getPortfolioValue(symbol) {
141 | try {
142 | // 从智能合约获取跟随者的投资组合价值
143 | const followers = await this.followTradeContract.getFollowers(symbol);
144 | let totalValue = 0;
145 |
146 | for (const follower of followers) {
147 | const balance = await this.followTradeContract.balances(follower);
148 | totalValue += balance.toNumber();
149 | }
150 |
151 | return totalValue;
152 | } catch (error) {
153 | console.error('Error getting portfolio value:', error);
154 | return 1000000; // 默认值
155 | }
156 | }
157 |
158 | async assessTradeRisk(signal, marketData) {
159 | try {
160 | const volatility = marketData.indicators.volatility;
161 | const volume = marketData.ohlcv.volume.mean();
162 | const price = marketData.ohlcv.close.last();
163 |
164 | // 计算风险分数
165 | let riskScore = 0.5; // 基础风险分数
166 |
167 | // 波动率调整
168 | if (volatility > 0.02) riskScore += 0.2;
169 | if (volatility > 0.05) riskScore += 0.3;
170 |
171 | // 成交量调整
172 | const avgVolume = volume * price;
173 | if (avgVolume < 1000000) riskScore += 0.2; // 流动性风险
174 |
175 | // 市场冲击成本
176 | const impact = marketData.orderbook ?
177 | this.tradingEngine.market_data.calculate_market_impact(marketData.orderbook, signal.position_size) :
178 | { buy_impact: 0, sell_impact: 0 };
179 |
180 | if (impact.buy_impact > 0.01 || impact.sell_impact > 0.01) {
181 | riskScore += 0.1;
182 | }
183 |
184 | return {
185 | riskScore: Math.min(riskScore, 1),
186 | factors: {
187 | volatility,
188 | volume: avgVolume,
189 | impact
190 | },
191 | recommendedSize: signal.position_size * (1 - riskScore)
192 | };
193 | } catch (error) {
194 | console.error('Error assessing trade risk:', error);
195 | return {
196 | riskScore: 1,
197 | factors: {},
198 | recommendedSize: 0
199 | };
200 | }
201 | }
202 |
203 | updatePerformanceMetrics(symbol, latency) {
204 | if (!this.performanceMetrics) {
205 | this.performanceMetrics = new Map();
206 | }
207 |
208 | const metrics = this.performanceMetrics.get(symbol) || {
209 | latencies: [],
210 | errors: 0,
211 | signalCount: 0
212 | };
213 |
214 | metrics.latencies.push(latency);
215 | metrics.signalCount++;
216 |
217 | if (metrics.latencies.length > 100) {
218 | metrics.latencies.shift();
219 | }
220 |
221 | this.performanceMetrics.set(symbol, metrics);
222 | }
223 |
224 | notifyError(symbol, error) {
225 | const subscribers = this.subscribers.get(symbol);
226 | if (!subscribers) return;
227 |
228 | const errorMessage = JSON.stringify({
229 | type: 'error',
230 | symbol,
231 | message: error.message,
232 | timestamp: Date.now()
233 | });
234 |
235 | subscribers.forEach(ws => {
236 | if (ws.readyState === ws.OPEN) {
237 | ws.send(errorMessage);
238 | }
239 | });
240 |
241 | this.updateErrorMetrics(symbol, error);
242 | }
243 |
244 | updateErrorMetrics(symbol, error) {
245 | if (!this.errorMetrics) {
246 | this.errorMetrics = new Map();
247 | }
248 |
249 | const metrics = this.errorMetrics.get(symbol) || {
250 | count: 0,
251 | lastError: null,
252 | timestamp: null
253 | };
254 |
255 | metrics.count++;
256 | metrics.lastError = error.message;
257 | metrics.timestamp = Date.now();
258 |
259 | this.errorMetrics.set(symbol, metrics);
260 | }
261 |
262 | async getPortfolioValue(symbol) {
263 | try {
264 | // 从智能合约获取跟随者的投资组合价值
265 | const followers = await this.followTradeContract.getFollowers(symbol);
266 | let totalValue = 0;
267 |
268 | for (const follower of followers) {
269 | const balance = await this.followTradeContract.balances(follower);
270 | totalValue += balance.toNumber();
271 | }
272 |
273 | return totalValue;
274 | } catch (error) {
275 | console.error('Error getting portfolio value:', error);
276 | return 1000000; // 默认值
277 | }
278 | }
279 |
280 | async assessTradeRisk(signal, marketData) {
281 | try {
282 | const volatility = marketData.indicators.volatility;
283 | const volume = marketData.ohlcv.volume.mean();
284 | const price = marketData.ohlcv.close.last();
285 |
286 | // 计算风险分数
287 | let riskScore = 0.5; // 基础风险分数
288 |
289 | // 波动率调整
290 | if (volatility > 0.02) riskScore += 0.2;
291 | if (volatility > 0.05) riskScore += 0.3;
292 |
293 | // 成交量调整
294 | const avgVolume = volume * price;
295 | if (avgVolume < 1000000) riskScore += 0.2; // 流动性风险
296 |
297 | // 市场冲击成本
298 | const impact = marketData.orderbook ?
299 | this.tradingEngine.market_data.calculate_market_impact(marketData.orderbook, signal.position_size) :
300 | { buy_impact: 0, sell_impact: 0 };
301 |
302 | if (impact.buy_impact > 0.01 || impact.sell_impact > 0.01) {
303 | riskScore += 0.1;
304 | }
305 |
306 | return {
307 | riskScore: Math.min(riskScore, 1),
308 | factors: {
309 | volatility,
310 | volume: avgVolume,
311 | impact
312 | },
313 | recommendedSize: signal.position_size * (1 - riskScore)
314 | };
315 | } catch (error) {
316 | console.error('Error assessing trade risk:', error);
317 | return {
318 | riskScore: 1,
319 | factors: {},
320 | recommendedSize: 0
321 | };
322 | }
323 | }
324 |
325 | updatePerformanceMetrics(symbol, latency) {
326 | if (!this.performanceMetrics) {
327 | this.performanceMetrics = new Map();
328 | }
329 |
330 | const metrics = this.performanceMetrics.get(symbol) || {
331 | latencies: [],
332 | errors: 0,
333 | signalCount: 0
334 | };
335 |
336 | metrics.latencies.push(latency);
337 | metrics.signalCount++;
338 |
339 | if (metrics.latencies.length > 100) {
340 | metrics.latencies.shift();
341 | }
342 |
343 | this.performanceMetrics.set(symbol, metrics);
344 | }
345 |
346 | updateErrorMetrics(symbol, error) {
347 | if (!this.errorMetrics) {
348 | this.errorMetrics = new Map();
349 | }
350 |
351 | const metrics = this.errorMetrics.get(symbol) || {
352 | count: 0,
353 | lastError: null,
354 | timestamp: null
355 | };
356 |
357 | metrics.count++;
358 | metrics.lastError = error.message;
359 | metrics.timestamp = Date.now();
360 |
361 | this.errorMetrics.set(symbol, metrics);
362 | }
363 | }
364 |
365 | module.exports = { RealTimeService };
--------------------------------------------------------------------------------
/src/services/social_media_service.js:
--------------------------------------------------------------------------------
1 | const axios = require('axios');
2 | const FormData = require('form-data');
3 | const fs = require('fs');
4 |
5 | class SocialMediaService {
6 | constructor(config) {
7 | this.config = config;
8 | this.platforms = {
9 | twitter: this.postToTwitter.bind(this),
10 | telegram: this.postToTelegram.bind(this),
11 | discord: this.postToDiscord.bind(this),
12 | reddit: this.postToReddit.bind(this),
13 | weibo: this.postToWeibo.bind(this)
14 | };
15 | }
16 |
17 | async postContent(content, platforms = ['twitter', 'telegram', 'discord', 'reddit', 'weibo']) {
18 | const results = [];
19 | for (const platform of platforms) {
20 | if (this.platforms[platform]) {
21 | try {
22 | const result = await this.platforms[platform](content);
23 | results.push({ platform, success: true, result });
24 | } catch (error) {
25 | console.error(`Error posting to ${platform}:`, error);
26 | results.push({ platform, success: false, error: error.message });
27 | }
28 | }
29 | }
30 | return results;
31 | }
32 |
33 | async postToTwitter(content) {
34 | const { text, mediaPath, replyToId } = content;
35 | const data = new FormData();
36 | data.append('text', text);
37 |
38 | if (mediaPath && fs.existsSync(mediaPath)) {
39 | data.append('media', fs.createReadStream(mediaPath));
40 | }
41 |
42 | if (replyToId) {
43 | data.append('reply', { in_reply_to_tweet_id: replyToId });
44 | }
45 |
46 | const response = await axios.post(
47 | 'https://api.twitter.com/2/tweets',
48 | data,
49 | {
50 | headers: {
51 | ...data.getHeaders(),
52 | 'Authorization': `Bearer ${this.config.twitter.accessToken}`
53 | }
54 | }
55 | );
56 |
57 | return response.data;
58 | }
59 |
60 | async postToTelegram(content) {
61 | const { text, mediaPath, replyToMessageId } = content;
62 | const method = mediaPath ? 'sendPhoto' : 'sendMessage';
63 | const data = mediaPath ?
64 | { photo: fs.createReadStream(mediaPath), caption: text } :
65 | { text };
66 |
67 | if (replyToMessageId) {
68 | data.reply_to_message_id = replyToMessageId;
69 | }
70 |
71 | const response = await axios.post(
72 | `https://api.telegram.org/bot${this.config.telegram.botToken}/${method}`,
73 | {
74 | chat_id: this.config.telegram.channelId,
75 | ...data
76 | },
77 | {
78 | headers: { 'Content-Type': 'application/json' }
79 | }
80 | );
81 |
82 | return response.data;
83 | }
84 |
85 | async postToDiscord(content) {
86 | const { text, mediaPath, threadId } = content;
87 | const data = { content: text };
88 |
89 | if (threadId) {
90 | data.thread_id = threadId;
91 | }
92 |
93 | if (mediaPath) {
94 | const form = new FormData();
95 | form.append('file', fs.createReadStream(mediaPath));
96 | form.append('payload_json', JSON.stringify(data));
97 |
98 | return await axios.post(
99 | this.config.discord.webhookUrl,
100 | form,
101 | { headers: form.getHeaders() }
102 | );
103 | }
104 |
105 | return await axios.post(
106 | this.config.discord.webhookUrl,
107 | data,
108 | { headers: { 'Content-Type': 'application/json' } }
109 | );
110 | }
111 |
112 | async postToReddit(content) {
113 | const { text, mediaPath, subreddit } = content;
114 | const data = {
115 | title: text.split('\n')[0],
116 | text: text,
117 | sr: subreddit || this.config.reddit.defaultSubreddit
118 | };
119 |
120 | if (mediaPath) {
121 | data.image = fs.createReadStream(mediaPath);
122 | }
123 |
124 | const response = await axios.post(
125 | 'https://oauth.reddit.com/api/submit',
126 | data,
127 | {
128 | headers: {
129 | 'Authorization': `Bearer ${this.config.reddit.accessToken}`,
130 | 'Content-Type': 'application/json'
131 | }
132 | }
133 | );
134 |
135 | return response.data;
136 | }
137 |
138 | async postToWeibo(content) {
139 | const { text, mediaPath } = content;
140 | const data = new FormData();
141 | data.append('status', text);
142 |
143 | if (mediaPath && fs.existsSync(mediaPath)) {
144 | data.append('pic', fs.createReadStream(mediaPath));
145 | }
146 |
147 | const response = await axios.post(
148 | 'https://api.weibo.com/2/statuses/share.json',
149 | data,
150 | {
151 | headers: {
152 | ...data.getHeaders(),
153 | 'Authorization': `OAuth2 ${this.config.weibo.accessToken}`
154 | }
155 | }
156 | );
157 |
158 | return response.data;
159 | }
160 |
161 | async distributeTradeContent(tradeData, memeImage, confessionVoice) {
162 | const content = {
163 | text: `🚨 Trade Alert! ${tradeData.symbol}\n` +
164 | `💰 Price: ${tradeData.price}\n` +
165 | `📊 P/L: ${tradeData.profit_loss}\n` +
166 | `${tradeData.description || ''}\n\n` +
167 | `#DeepRug #Trading #Crypto ${tradeData.tags || ''}`,
168 | mediaPath: memeImage
169 | };
170 |
171 | // 首先发布Meme图片
172 | const memeResults = await this.postContent(content);
173 |
174 | // 如果有认罪语音,作为单独的内容发布
175 | if (confessionVoice) {
176 | const voiceContent = {
177 | text: `🎤 Trader's Confession 😅\n` +
178 | `Listen to what happened with ${tradeData.symbol} 🔊\n` +
179 | `#TraderConfession #CryptoLife`,
180 | mediaPath: confessionVoice
181 | };
182 | const voiceResults = await this.postContent(voiceContent);
183 | return [...memeResults, ...voiceResults];
184 | }
185 |
186 | return memeResults;
187 | }
188 |
189 | async createThread(content, platforms = ['discord']) {
190 | const results = [];
191 | for (const platform of platforms) {
192 | if (platform === 'discord' && this.platforms[platform]) {
193 | try {
194 | const result = await this.platforms[platform]({
195 | ...content,
196 | createThread: true
197 | });
198 | results.push({ platform, success: true, result });
199 | } catch (error) {
200 | console.error(`Error creating thread on ${platform}:`, error);
201 | results.push({ platform, success: false, error: error.message });
202 | }
203 | }
204 | }
205 | return results;
206 | }
207 | }
208 |
209 | module.exports = SocialMediaService;
--------------------------------------------------------------------------------
/src/services/trading_service.js:
--------------------------------------------------------------------------------
1 | const { Connection, PublicKey, Transaction, SystemProgram } = require('@solana/web3.js');
2 | const { Program } = require('@project-serum/anchor');
3 | const { TradingEngine } = require('../ai_engine/trading_engine');
4 | const WebSocket = require('ws');
5 |
6 | class TradingService {
7 | constructor(endpoint, programId) {
8 | // Initialize Solana connection
9 | this.connection = new Connection(endpoint);
10 | this.programId = new PublicKey(programId);
11 |
12 | // Initialize trading engine
13 | this.tradingEngine = new TradingEngine();
14 |
15 | // Active trading signals
16 | this.activeSignals = new Map();
17 |
18 | // Initialize WebSocket server
19 | this.wss = new WebSocket.Server({ port: 8080 });
20 | this.clients = new Map();
21 |
22 | this.setupWebSocket();
23 | }
24 |
25 | setupWebSocket() {
26 | this.wss.on('connection', (ws) => {
27 | ws.on('message', async (message) => {
28 | try {
29 | const data = JSON.parse(message);
30 |
31 | if (data.type === 'subscribe') {
32 | this.clients.set(ws, {
33 | publicKey: data.publicKey,
34 | symbols: new Set(data.symbols)
35 | });
36 | }
37 | } catch (error) {
38 | console.error('Error processing WebSocket message:', error);
39 | }
40 | });
41 |
42 | ws.on('close', () => {
43 | this.clients.delete(ws);
44 | });
45 | });
46 | }
47 |
48 | broadcastSignal(symbol, signal) {
49 | this.clients.forEach((client, ws) => {
50 | if (client.symbols.has(symbol) && ws.readyState === WebSocket.OPEN) {
51 | ws.send(JSON.stringify({
52 | type: 'signal',
53 | symbol,
54 | signal
55 | }));
56 | }
57 | });
58 | }
59 |
60 | notifyFollowSuccess(userPublicKey, symbol, signal) {
61 | this.clients.forEach((client, ws) => {
62 | if (client.publicKey === userPublicKey && ws.readyState === WebSocket.OPEN) {
63 | ws.send(JSON.stringify({
64 | type: 'follow_success',
65 | symbol,
66 | signal
67 | }));
68 | }
69 | });
70 | }
71 |
72 | async generateAndBroadcastSignal(symbol) {
73 | try {
74 | // Fetch market data and generate signal
75 | const marketData = await this.tradingEngine.fetch_market_data(symbol);
76 | const signal = await this.tradingEngine.generate_trading_signal(marketData);
77 |
78 | if (signal) {
79 | // Store active signal
80 | this.activeSignals.set(symbol, {
81 | ...signal,
82 | followers: new Set()
83 | });
84 |
85 | // Broadcast signal to connected clients
86 | this.broadcastSignal(symbol, signal);
87 | }
88 |
89 | return signal;
90 | } catch (error) {
91 | console.error('Error generating trading signal:', error);
92 | return null;
93 | }
94 | }
95 |
96 | async followTrade(userPublicKey, symbol) {
97 | try {
98 | // Check if signal exists
99 | const signal = this.activeSignals.get(symbol);
100 | if (!signal) {
101 | throw new Error('No active signal for this symbol');
102 | }
103 |
104 | // Check if user is already following
105 | if (signal.followers.has(userPublicKey)) {
106 | throw new Error('Already following this signal');
107 | }
108 |
109 | // Create follow trade instruction
110 | const instruction = await this.program.instruction.followTrade({
111 | accounts: {
112 | user: userPublicKey,
113 | systemProgram: SystemProgram.programId,
114 | },
115 | signers: [userPublicKey]
116 | });
117 |
118 | // Add user to followers
119 | signal.followers.add(userPublicKey);
120 |
121 | // Notify user of successful follow
122 | this.notifyFollowSuccess(userPublicKey, symbol, signal);
123 |
124 | return true;
125 | } catch (error) {
126 | console.error('Error following trade:', error);
127 | return false;
128 | }
129 | }
130 |
131 | async startTradingStream(symbols = ['BTC/USDT', 'ETH/USDT']) {
132 | // Start periodic signal generation
133 | setInterval(async () => {
134 | for (const symbol of symbols) {
135 | await this.generateAndBroadcastSignal(symbol);
136 | }
137 | }, 60000); // Generate signals every minute
138 | }
139 | throw new Error('No active signal for this symbol');
140 | }
141 |
142 | // Create transaction for follow trade fee
143 | const transaction = new Transaction();
144 | const instruction = await this.program.methods
145 | .payFollowTradeFee()
146 | .accounts({
147 | user: userPublicKey,
148 | // Add other required accounts based on your program structure
149 | })
150 | .instruction();
151 |
152 | transaction.add(instruction);
153 |
154 | // Send and confirm transaction
155 | const signature = await this.connection.sendTransaction(transaction, []);
156 | const confirmation = await this.connection.confirmTransaction(signature);
157 |
158 | if (confirmation.value.err === null) {
159 | // Add user to signal followers
160 | signal.followers.add(userPublicKey.toString());
161 |
162 | // Notify user of successful follow
163 | this.notifyFollowSuccess(userPublicKey.toString(), symbol, signal);
164 | return true;
165 | }
166 |
167 | return false;
168 | } catch (error) {
169 | console.error('Error following trade:', error);
170 | return false;
171 | }
172 | }
173 |
174 | broadcastSignal(symbol, signal) {
175 | // This method should be implemented to work with your WebSocket system
176 | // to broadcast signals to connected clients
177 | console.log(`Broadcasting signal for ${symbol}:`, signal);
178 | }
179 |
180 | notifyFollowSuccess(userPublicKey, symbol, signal) {
181 | // This method should be implemented to notify users of successful follows
182 | console.log(`User ${userPublicKey} successfully followed ${symbol} signal`);
183 | }
184 | }
185 |
186 | module.exports = TradingService;
--------------------------------------------------------------------------------