This commit is contained in:
lz_db
2025-12-02 22:36:52 +08:00
parent 7fa249a767
commit c8a6cfead1
6 changed files with 466 additions and 197 deletions

View File

@@ -1,10 +1,12 @@
from abc import ABC, abstractmethod
from loguru import logger
from typing import List, Dict, Any
from typing import List, Dict, Any, Set
import json
import re
from utils.redis_client import RedisClient
from utils.database_manager import DatabaseManager
from config.settings import COMPUTER_NAMES, COMPUTER_NAME_PATTERN
class BaseSync(ABC):
"""同步基类"""
@@ -12,27 +14,50 @@ class BaseSync(ABC):
def __init__(self):
self.redis_client = RedisClient()
self.db_manager = DatabaseManager()
self.computer_name = None # 从配置读取
self.computer_names = self._get_computer_names()
self.computer_name_pattern = re.compile(COMPUTER_NAME_PATTERN)
@abstractmethod
async def sync(self):
"""执行同步"""
pass
def _get_computer_names(self) -> List[str]:
"""获取计算机名列表"""
if ',' in COMPUTER_NAMES:
return [name.strip() for name in COMPUTER_NAMES.split(',')]
return [COMPUTER_NAMES.strip()]
def get_accounts_from_redis(self) -> Dict[str, Dict]:
"""从Redis获取账号配置"""
"""从Redis获取所有计算机名的账号配置"""
try:
if self.computer_name is None:
from config.settings import COMPUTER_NAME
self.computer_name = COMPUTER_NAME
accounts_dict = {}
# 方法1使用配置的计算机名列表
for computer_name in self.computer_names:
accounts = self._get_accounts_by_computer_name(computer_name)
accounts_dict.update(accounts)
# 方法2自动发现所有匹配的key备用方案
if not accounts_dict:
accounts_dict = self._discover_all_accounts()
logger.info(f"{len(self.computer_names)} 个计算机名获取到 {len(accounts_dict)} 个账号")
return accounts_dict
except Exception as e:
logger.error(f"获取账户信息失败: {e}")
return {}
def _get_accounts_by_computer_name(self, computer_name: str) -> Dict[str, Dict]:
"""获取指定计算机名的账号"""
accounts_dict = {}
try:
# 构建key
redis_key = f"{computer_name}_strategy_api"
# 从Redis获取数据
result = self.redis_client.client.hgetall(f"{self.computer_name}_strategy_api")
result = self.redis_client.client.hgetall(redis_key)
if not result:
logger.warning(f"未找到 {self.computer_name} 的策略API配置")
logger.debug(f"未找到 {redis_key} 的策略API配置")
return {}
accounts_dict = {}
for exchange_name, accounts_json in result.items():
try:
accounts = json.loads(accounts_json)
@@ -45,46 +70,52 @@ class BaseSync(ABC):
for account_id, account_info in accounts.items():
parsed_account = self.parse_account(exchange_id, account_id, account_info)
if parsed_account:
# 添加计算机名标记
parsed_account['computer_name'] = computer_name
accounts_dict[account_id] = parsed_account
except json.JSONDecodeError as e:
logger.error(f"解析交易所 {exchange_name} 的JSON数据失败: {e}")
continue
return accounts_dict
logger.info(f"{redis_key} 获取到 {len(accounts_dict)} 个账号")
except Exception as e:
logger.error(f"获取账户信息失败: {e}")
return {}
def format_exchange_id(self, key: str) -> str:
"""格式化交易所ID"""
key = key.lower().strip()
logger.error(f"获取计算机名 {computer_name} 的账号失败: {e}")
# 交易所名称映射
exchange_mapping = {
'metatrader': 'mt5',
'binance_spot_test': 'binance',
'binance_spot': 'binance',
'binance': 'binance',
'gate_spot': 'gate',
'okex': 'okx'
}
return exchange_mapping.get(key, key)
return accounts_dict
def parse_account(self, exchange_id: str, account_id: str, account_info: str) -> Dict:
"""解析账号信息"""
def _discover_all_accounts(self) -> Dict[str, Dict]:
"""自动发现所有匹配的账号key"""
accounts_dict = {}
try:
source_account_info = json.loads(account_info)
account_data = {
'exchange_id': exchange_id,
'k_id': account_id,
'st_id': int(source_account_info.get('st_id', 0)),
'add_time': int(source_account_info.get('add_time', 0))
}
return {**source_account_info, **account_data}
# 获取所有匹配模式的key
pattern = f"*_strategy_api"
cursor = 0
except json.JSONDecodeError as e:
logger.error(f"解析账号 {account_id} 数据失败: {e}")
return {}
while True:
cursor, keys = self.redis_client.client.scan(cursor, match=pattern, count=100)
for key in keys:
key_str = key.decode('utf-8') if isinstance(key, bytes) else key
# 提取计算机名
computer_name = key_str.replace('_strategy_api', '')
# 验证计算机名格式
if self.computer_name_pattern.match(computer_name):
accounts = self._get_accounts_by_computer_name(computer_name)
accounts_dict.update(accounts)
if cursor == 0:
break
logger.info(f"自动发现 {len(accounts_dict)} 个账号")
except Exception as e:
logger.error(f"自动发现账号失败: {e}")
return accounts_dict
# 其他方法保持不变...