This commit is contained in:
ddrwode
2026-02-20 22:16:02 +08:00
parent 8c6dd81844
commit fa48f70758
2 changed files with 49 additions and 9 deletions

1
111 Normal file
View File

@@ -0,0 +1 @@
1600

View File

@@ -65,6 +65,14 @@ class BitmartFuturesTransaction:
self.prev_entity = None # 上一根K线实体大小
self.current_open = None # 当前K线开盘价
# API 节流:主循环与持仓/价格查询间隔,避免 429 Request too many requests
self.loop_interval_seconds = 2.5 # 每轮循环最少间隔(秒)
self._last_position_fetch = 0.0
self._last_price_fetch = 0.0
self._position_refresh_interval = 2.0 # 持仓/价格最少隔多久才重新请求(秒)
self._position_cache = None # 上次成功的持仓状态,用于节流时复用
self._price_cache = None # 上次成功的价格,用于节流时复用
def get_klines(self):
"""获取最近2根K线当前K线和上一根K线"""
try:
@@ -99,9 +107,12 @@ class BitmartFuturesTransaction:
return None, None
def get_current_price(self):
"""获取当前最新价格"""
"""获取当前最新价格(带节流:间隔内返回缓存值)"""
now = time.time()
if self._price_cache is not None and (now - self._last_price_fetch) < self._position_refresh_interval:
return self._price_cache
try:
end_time = int(time.time())
end_time = int(now)
response = self.contractAPI.get_kline(
contract_symbol=self.contract_symbol,
step=1, # 1分钟
@@ -109,11 +120,14 @@ class BitmartFuturesTransaction:
end_time=end_time
)[0]
if response['code'] == 1000:
return float(response['data'][-1]["close_price"])
return None
price = float(response['data'][-1]["close_price"])
self._price_cache = price
self._last_price_fetch = now
return price
return self._price_cache # 失败时用旧价格
except Exception as e:
logger.error(f"获取价格异常: {e}")
return None
return self._price_cache
def get_available_balance(self):
"""获取合约账户可用USDT余额"""
@@ -133,7 +147,15 @@ class BitmartFuturesTransaction:
return None
def get_position_status(self):
"""获取当前持仓方向"""
"""获取当前持仓方向(带节流:间隔内返回缓存状态)"""
now = time.time()
if self._position_cache is not None and (now - self._last_position_fetch) < self._position_refresh_interval:
c = self._position_cache
self.start = c['start']
self.open_avg_price = c.get('open_avg_price')
self.current_amount = c.get('current_amount')
self.unrealized_pnl = c.get('unrealized_pnl')
return True
try:
response = self.contractAPI.get_position(contract_symbol=self.contract_symbol)[0]
if response['code'] == 1000:
@@ -143,21 +165,34 @@ class BitmartFuturesTransaction:
self.open_avg_price = None
self.current_amount = None
self.unrealized_pnl = None
self._position_cache = {'start': 0, 'open_avg_price': None, 'current_amount': None, 'unrealized_pnl': None}
self._last_position_fetch = now
return True
pos = positions[0]
self.start = 1 if pos['position_type'] == 1 else -1
self.open_avg_price = float(pos['open_avg_price'])
self.current_amount = float(pos['current_amount'])
self.position_cross = pos["position_cross"]
# 直接从API获取未实现盈亏Bitmart返回的是 unrealized_value 字段)
self.unrealized_pnl = float(pos.get('unrealized_value', 0))
self._position_cache = {'start': self.start, 'open_avg_price': self.open_avg_price, 'current_amount': self.current_amount, 'unrealized_pnl': self.unrealized_pnl}
self._last_position_fetch = now
logger.debug(f"持仓详情: 方向={self.start}, 开仓均价={self.open_avg_price}, "
f"持仓量={self.current_amount}, 未实现盈亏={self.unrealized_pnl:.2f}")
return True
else:
if self._position_cache is not None:
c = self._position_cache
self.start, self.open_avg_price = c['start'], c.get('open_avg_price')
self.current_amount, self.unrealized_pnl = c.get('current_amount'), c.get('unrealized_pnl')
return True # 请求失败但用缓存
return False
except Exception as e:
logger.error(f"持仓查询异常: {e}")
if self._position_cache is not None:
c = self._position_cache
self.start, self.open_avg_price = c['start'], c.get('open_avg_price')
self.current_amount, self.unrealized_pnl = c.get('current_amount'), c.get('unrealized_pnl')
return True # 429 等异常时用缓存
return False
def get_unrealized_pnl_usd(self):
@@ -492,6 +527,7 @@ class BitmartFuturesTransaction:
self.max_unrealized_pnl_seen = None # 新仓位重置移动止损记录
self.last_open_time = time.time()
self.last_open_kline_id = getattr(self, "_current_kline_id_for_open", None)
self._last_position_fetch = 0 # 强制下一轮重新拉持仓
logger.success("开多成功")
return True
else:
@@ -517,6 +553,7 @@ class BitmartFuturesTransaction:
self.max_unrealized_pnl_seen = None # 新仓位重置移动止损记录
self.last_open_time = time.time()
self.last_open_kline_id = getattr(self, "_current_kline_id_for_open", None)
self._last_position_fetch = 0 # 强制下一轮重新拉持仓
logger.success("开空成功")
return True
else:
@@ -542,6 +579,7 @@ class BitmartFuturesTransaction:
if self.verify_position_direction(1):
self.max_unrealized_pnl_seen = None
self._last_position_fetch = 0 # 强制下一轮重新拉持仓
logger.success("反手做多成功")
self.last_reverse_time = time.time()
time.sleep(20)
@@ -568,6 +606,7 @@ class BitmartFuturesTransaction:
if self.verify_position_direction(-1):
self.max_unrealized_pnl_seen = None
self._last_position_fetch = 0 # 强制下一轮重新拉持仓
logger.success("反手做空成功")
self.last_reverse_time = time.time()
time.sleep(20)
@@ -698,8 +737,8 @@ class BitmartFuturesTransaction:
else:
logger.warning(f"交易执行失败或被阻止: {signal[0]}")
# 短暂等待后继续循环同一根K线遇到信号就操作
time.sleep(0.1)
# 主循环间隔,避免持仓/价格查询过于频繁触发 429
time.sleep(self.loop_interval_seconds)
if page_start:
self.page.close()