This commit is contained in:
薇薇安 2026-01-14 19:17:22 +08:00
parent dee37d3c78
commit b0e7ae8ef2
5 changed files with 119 additions and 2 deletions

View File

@ -114,6 +114,9 @@ INSERT INTO `trading_config` (`config_key`, `config_value`, `config_type`, `cate
('TRAILING_STOP_ACTIVATION', '0.01', 'number', 'strategy', '移动止损激活阈值盈利1%后激活)'),
('TRAILING_STOP_PROTECT', '0.01', 'number', 'strategy', '移动止损保护利润保护1%利润)'),
-- 持仓同步
('POSITION_SYNC_INTERVAL', '300', 'number', 'scan', '持仓状态同步间隔默认5分钟用于同步币安实际持仓与数据库状态'),
-- API配置
('BINANCE_API_KEY', '', 'string', 'api', '币安API密钥'),

View File

@ -51,11 +51,13 @@ def init_configs():
config_type = 'string'
# 确定分类
if 'POSITION' in key:
if key == 'TOP_N_SYMBOLS' or key == 'MAX_SCAN_SYMBOLS' or key == 'POSITION_SYNC_INTERVAL':
category = 'scan'
elif 'POSITION' in key and 'SYNC' not in key:
category = 'position'
elif 'RISK' in key or 'STOP' in key or 'PROFIT' in key:
category = 'risk'
elif 'SCAN' in key or 'INTERVAL' in key or 'VOLUME' in key or 'TOP_N_SYMBOLS' in key or 'MAX_SCAN_SYMBOLS' in key:
elif 'SCAN' in key or 'INTERVAL' in key or 'VOLUME' in key:
category = 'scan'
else:
category = 'strategy'

View File

@ -156,6 +156,7 @@ def _get_trading_config():
'USE_TRAILING_STOP': True,
'TRAILING_STOP_ACTIVATION': 0.01,
'TRAILING_STOP_PROTECT': 0.01,
'POSITION_SYNC_INTERVAL': 300, # 持仓状态同步间隔默认5分钟
}
# 币安API配置优先从数据库回退到环境变量和默认值

View File

@ -653,6 +653,79 @@ class PositionManager:
f"发现 {len(missing_in_db)} 个持仓在币安存在但数据库中没有记录: "
f"{', '.join(missing_in_db)} (可能是手动开仓)"
)
# 为手动开仓的持仓创建数据库记录并启动监控
for symbol in missing_in_db:
try:
# 获取币安持仓详情
binance_position = next(
(p for p in binance_positions if p['symbol'] == symbol),
None
)
if not binance_position:
continue
position_amt = binance_position['positionAmt']
entry_price = binance_position['entryPrice']
quantity = abs(position_amt)
side = 'BUY' if position_amt > 0 else 'SELL'
logger.info(
f"{symbol} [状态同步] 检测到手动开仓,创建数据库记录... "
f"({side} {quantity:.4f} @ {entry_price:.4f})"
)
# 创建数据库记录
trade_id = Trade.create(
symbol=symbol,
side=side,
quantity=quantity,
entry_price=entry_price,
leverage=binance_position.get('leverage', 10),
entry_reason='manual_entry' # 标记为手动开仓
)
logger.info(f"{symbol} [状态同步] ✓ 数据库记录已创建 (ID: {trade_id})")
# 创建本地持仓记录(用于监控)
ticker = await self.client.get_ticker_24h(symbol)
current_price = ticker['price'] if ticker else entry_price
# 计算止损止盈
stop_loss_price = self.risk_manager.get_stop_loss_price(entry_price, side)
take_profit_price = self.risk_manager.get_take_profit_price(entry_price, side)
position_info = {
'symbol': symbol,
'side': side,
'quantity': quantity,
'entryPrice': entry_price,
'changePercent': 0, # 手动开仓,无法计算涨跌幅
'orderId': None,
'tradeId': trade_id,
'stopLoss': stop_loss_price,
'takeProfit': take_profit_price,
'initialStopLoss': stop_loss_price,
'leverage': binance_position.get('leverage', 10),
'entryReason': 'manual_entry',
'atr': None,
'maxProfit': 0.0,
'trailingStopActivated': False
}
self.active_positions[symbol] = position_info
# 启动WebSocket监控
if self._monitoring_enabled:
await self._start_position_monitoring(symbol)
logger.info(f"{symbol} [状态同步] ✓ 已启动实时监控")
logger.info(f"{symbol} [状态同步] ✓ 手动开仓同步完成")
except Exception as e:
logger.error(f"{symbol} [状态同步] ❌ 处理手动开仓失败: {e}")
import traceback
logger.error(f" 错误详情:\n{traceback.format_exc()}")
logger.info("持仓状态同步完成")

View File

@ -45,6 +45,7 @@ class TradingStrategy:
self.position_manager = position_manager
self.running = False
self._monitoring_started = False # 是否已启动监控
self._sync_task = None # 定期同步任务
async def execute_strategy(self):
"""
@ -61,6 +62,10 @@ class TradingStrategy:
except Exception as e:
logger.warning(f"启动持仓监控失败: {e},将使用定时检查模式")
# 启动定期同步任务(独立于市场扫描)
self._sync_task = asyncio.create_task(self._periodic_sync_positions())
logger.info("定期持仓同步任务已启动")
try:
while self.running:
# 1. 扫描市场找出涨跌幅最大的前N个货币对
@ -216,6 +221,14 @@ class TradingStrategy:
logger.error(f"策略执行出错: {e}", exc_info=True)
finally:
self.running = False
# 停止定期同步任务
if self._sync_task:
self._sync_task.cancel()
try:
await self._sync_task
except asyncio.CancelledError:
pass
logger.info("定期持仓同步任务已停止")
# 停止所有持仓的WebSocket监控
try:
await self.position_manager.stop_all_position_monitoring()
@ -366,6 +379,31 @@ class TradingStrategy:
'strength': signal_strength
}
async def _periodic_sync_positions(self):
"""
定期同步币安持仓状态独立任务不依赖市场扫描
"""
sync_interval = config.TRADING_CONFIG.get('POSITION_SYNC_INTERVAL', 300) # 默认5分钟
logger.info(f"定期持仓同步任务启动,同步间隔: {sync_interval}")
while self.running:
try:
await asyncio.sleep(sync_interval)
if not self.running:
break
logger.debug("执行定期持仓状态同步...")
await self.position_manager.sync_positions_with_binance()
except asyncio.CancelledError:
logger.info("定期持仓同步任务已取消")
break
except Exception as e:
logger.error(f"定期持仓同步任务出错: {e}")
# 出错后等待一段时间再继续
await asyncio.sleep(60)
def stop(self):
"""停止策略"""
self.running = False