138 lines
5.3 KiB
Python
138 lines
5.3 KiB
Python
|
|
from typing import List, Dict, Any, Tuple
|
||
|
|
from loguru import logger
|
||
|
|
from sqlalchemy import text
|
||
|
|
from .database_manager import DatabaseManager
|
||
|
|
|
||
|
|
class BatchOperations:
|
||
|
|
"""批量数据库操作工具"""
|
||
|
|
|
||
|
|
def __init__(self):
|
||
|
|
self.db_manager = DatabaseManager()
|
||
|
|
|
||
|
|
def batch_insert_update_positions(self, positions_data: List[Dict]) -> Tuple[int, int]:
|
||
|
|
"""批量插入/更新持仓数据"""
|
||
|
|
session = self.db_manager.get_session()
|
||
|
|
try:
|
||
|
|
if not positions_data:
|
||
|
|
return 0, 0
|
||
|
|
|
||
|
|
# 按账号分组
|
||
|
|
positions_by_account = {}
|
||
|
|
for position in positions_data:
|
||
|
|
k_id = position.get('k_id')
|
||
|
|
if k_id not in positions_by_account:
|
||
|
|
positions_by_account[k_id] = []
|
||
|
|
positions_by_account[k_id].append(position)
|
||
|
|
|
||
|
|
total_processed = 0
|
||
|
|
total_deleted = 0
|
||
|
|
|
||
|
|
with session.begin():
|
||
|
|
for k_id, positions in positions_by_account.items():
|
||
|
|
processed, deleted = self._process_account_positions(session, k_id, positions)
|
||
|
|
total_processed += processed
|
||
|
|
total_deleted += deleted
|
||
|
|
|
||
|
|
logger.info(f"批量处理持仓完成: 处理 {total_processed} 条,删除 {total_deleted} 条")
|
||
|
|
return total_processed, total_deleted
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"批量处理持仓失败: {e}")
|
||
|
|
return 0, 0
|
||
|
|
finally:
|
||
|
|
session.close()
|
||
|
|
|
||
|
|
def _process_account_positions(self, session, k_id: int, positions: List[Dict]) -> Tuple[int, int]:
|
||
|
|
"""处理单个账号的持仓数据"""
|
||
|
|
try:
|
||
|
|
st_id = positions[0].get('st_id', 0) if positions else 0
|
||
|
|
|
||
|
|
# 准备数据
|
||
|
|
insert_data = []
|
||
|
|
keep_keys = set()
|
||
|
|
|
||
|
|
for pos_data in positions:
|
||
|
|
# 转换数据
|
||
|
|
pos_dict = self._convert_position_data(pos_data)
|
||
|
|
if not all([pos_dict.get('symbol'), pos_dict.get('side')]):
|
||
|
|
continue
|
||
|
|
|
||
|
|
# 重命名qty为sum
|
||
|
|
if 'qty' in pos_dict:
|
||
|
|
pos_dict['sum'] = pos_dict.pop('qty')
|
||
|
|
|
||
|
|
insert_data.append(pos_dict)
|
||
|
|
keep_keys.add((pos_dict['symbol'], pos_dict['side']))
|
||
|
|
|
||
|
|
if not insert_data:
|
||
|
|
# 清空该账号持仓
|
||
|
|
result = session.execute(
|
||
|
|
text("DELETE FROM deh_strategy_position_new WHERE k_id = :k_id AND st_id = :st_id"),
|
||
|
|
{'k_id': k_id, 'st_id': st_id}
|
||
|
|
)
|
||
|
|
return 0, result.rowcount
|
||
|
|
|
||
|
|
# 批量插入/更新
|
||
|
|
sql = """
|
||
|
|
INSERT INTO deh_strategy_position_new
|
||
|
|
(st_id, k_id, asset, symbol, side, price, `sum`,
|
||
|
|
asset_num, asset_profit, leverage, uptime,
|
||
|
|
profit_price, stop_price, liquidation_price)
|
||
|
|
VALUES
|
||
|
|
(:st_id, :k_id, :asset, :symbol, :side, :price, :sum,
|
||
|
|
:asset_num, :asset_profit, :leverage, :uptime,
|
||
|
|
:profit_price, :stop_price, :liquidation_price)
|
||
|
|
ON DUPLICATE KEY UPDATE
|
||
|
|
price = VALUES(price),
|
||
|
|
`sum` = VALUES(`sum`),
|
||
|
|
asset_num = VALUES(asset_num),
|
||
|
|
asset_profit = VALUES(asset_profit),
|
||
|
|
leverage = VALUES(leverage),
|
||
|
|
uptime = VALUES(uptime),
|
||
|
|
profit_price = VALUES(profit_price),
|
||
|
|
stop_price = VALUES(stop_price),
|
||
|
|
liquidation_price = VALUES(liquidation_price)
|
||
|
|
"""
|
||
|
|
|
||
|
|
# 分块执行
|
||
|
|
chunk_size = 500
|
||
|
|
processed_count = 0
|
||
|
|
|
||
|
|
for i in range(0, len(insert_data), chunk_size):
|
||
|
|
chunk = insert_data[i:i + chunk_size]
|
||
|
|
session.execute(text(sql), chunk)
|
||
|
|
processed_count += len(chunk)
|
||
|
|
|
||
|
|
# 删除多余持仓
|
||
|
|
deleted_count = 0
|
||
|
|
if keep_keys:
|
||
|
|
# 构建删除条件
|
||
|
|
conditions = []
|
||
|
|
for symbol, side in keep_keys:
|
||
|
|
safe_symbol = symbol.replace("'", "''") if symbol else ''
|
||
|
|
safe_side = side.replace("'", "''") if side else ''
|
||
|
|
conditions.append(f"(symbol = '{safe_symbol}' AND side = '{safe_side}')")
|
||
|
|
|
||
|
|
if conditions:
|
||
|
|
conditions_str = " OR ".join(conditions)
|
||
|
|
delete_sql = f"""
|
||
|
|
DELETE FROM deh_strategy_position_new
|
||
|
|
WHERE k_id = {k_id} AND st_id = {st_id}
|
||
|
|
AND NOT ({conditions_str})
|
||
|
|
"""
|
||
|
|
|
||
|
|
result = session.execute(text(delete_sql))
|
||
|
|
deleted_count = result.rowcount
|
||
|
|
|
||
|
|
return processed_count, deleted_count
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
logger.error(f"处理账号 {k_id} 持仓失败: {e}")
|
||
|
|
return 0, 0
|
||
|
|
|
||
|
|
def _convert_position_data(self, data: Dict) -> Dict:
|
||
|
|
"""转换持仓数据格式"""
|
||
|
|
# 转换逻辑...
|
||
|
|
pass
|
||
|
|
|
||
|
|
# 类似的批量方法 for orders and account info...
|