356 lines
12 KiB
Python
356 lines
12 KiB
Python
"""
|
||
Hyperliquid 小资金测试脚本
|
||
|
||
测试内容:
|
||
1. 获取账户状态
|
||
2. 市价单测试(小金额)
|
||
3. 限价单测试(小金额)
|
||
4. 止盈止损设置
|
||
5. 查询持仓和挂单
|
||
6. 清理测试(平仓、取消挂单)
|
||
|
||
运行方式:
|
||
python3 test_hyperliquid_operations.py
|
||
|
||
⚠️ 请确保 .env 中已配置:
|
||
- CLAWFI_WALLET_ADDRESS
|
||
- CLAWFI_PRIVATE_KEY
|
||
- hyperliquid_trading_enabled=true
|
||
"""
|
||
import sys
|
||
import os
|
||
import time
|
||
|
||
# 添加项目路径
|
||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
||
|
||
from app.services.hyperliquid_trading_service import HyperliquidTradingService
|
||
from app.utils.logger import logger
|
||
|
||
|
||
class HyperliquidTester:
|
||
"""Hyperliquid 测试器"""
|
||
|
||
def __init__(self):
|
||
"""初始化测试器"""
|
||
try:
|
||
self.service = HyperliquidTradingService()
|
||
logger.info("✅ Hyperliquid 服务初始化成功")
|
||
except Exception as e:
|
||
logger.error(f"❌ 初始化失败: {e}")
|
||
raise
|
||
|
||
def print_section(self, title: str):
|
||
"""打印分隔线"""
|
||
print(f"\n{'='*60}")
|
||
print(f" {title}")
|
||
print(f"{'='*60}\n")
|
||
|
||
def test_1_get_account_state(self):
|
||
"""测试1:获取账户状态"""
|
||
self.print_section("测试1: 获取账户状态")
|
||
|
||
state = self.service.get_account_state()
|
||
|
||
print(f"💰 账户价值: ${state['account_value']:,.2f}")
|
||
print(f"📊 已用保证金: ${state['total_margin_used']:,.2f}")
|
||
print(f"💵 可用余额: ${state['available_balance']:,.2f}")
|
||
print(f"📈 持仓数量: {len(state['positions'])}")
|
||
|
||
positions = self.service.get_open_positions()
|
||
if positions:
|
||
print(f"\n当前持仓:")
|
||
for pos in positions:
|
||
coin = pos['coin']
|
||
size = pos['size']
|
||
entry = pos['entry_price']
|
||
pnl = pos['unrealized_pnl']
|
||
print(f" - {coin}: {size:.4f} @ ${entry:,.2f} | PnL: ${pnl:,.2f}")
|
||
else:
|
||
print(f" 无持仓")
|
||
|
||
return state
|
||
|
||
def test_2_market_order(self, symbol: str = "BTC", is_buy: bool = True, size: float = 0.001):
|
||
"""测试2:市价单(小金额测试)"""
|
||
self.print_section(f"测试2: 市价单 - {'买入' if is_buy else '卖出'} {symbol}")
|
||
|
||
# 检查风险限制
|
||
risk = self.service.check_risk_limits()
|
||
print(f"🔍 风险检查:")
|
||
print(f" 初始余额: ${risk['initial_balance']:,.2f}")
|
||
print(f" 当前价值: ${risk['current_value']:,.2f}")
|
||
print(f" 回撤: {risk['drawdown_percent']:.2f}%")
|
||
print(f" 安全交易: {'✅' if risk['safe_to_trade'] else '❌'}")
|
||
|
||
if not risk['safe_to_trade']:
|
||
print("⚠️ 风险检查未通过,跳过测试")
|
||
return None
|
||
|
||
# 更新杠杆
|
||
print(f"\n⚙️ 设置杠杆为 2x...")
|
||
self.service.update_leverage(symbol, 2)
|
||
|
||
# 下市价单
|
||
print(f"\n📝 下市价单: {'买入' if is_buy else '卖出'} {size} {symbol}")
|
||
result = self.service.place_market_order(
|
||
symbol=symbol,
|
||
is_buy=is_buy,
|
||
size=size
|
||
)
|
||
|
||
if result.get('success'):
|
||
print(f"✅ 市价单成功")
|
||
print(f" 方向: {'买入' if is_buy else '卖出'}")
|
||
print(f" 数量: {size}")
|
||
print(f" 结果: {result.get('result')}")
|
||
|
||
# 设置止盈止损
|
||
print(f"\n🎯 设置止盈止损...")
|
||
current_positions = self.service.get_open_positions()
|
||
if current_positions:
|
||
pos = current_positions[0]
|
||
entry_price = pos['entry_price']
|
||
is_long = pos['size'] > 0
|
||
|
||
# 计算止盈止损价格(小范围测试)
|
||
if is_long:
|
||
tp_price = entry_price * 1.01 # +1%
|
||
sl_price = entry_price * 0.995 # -0.5%
|
||
else:
|
||
tp_price = entry_price * 0.99 # -1%
|
||
sl_price = entry_price * 1.005 # +0.5%
|
||
|
||
print(f" 入场价: ${entry_price:,.2f}")
|
||
print(f" 止盈价: ${tp_price:,.2f}")
|
||
print(f" 止损价: ${sl_price:,.2f}")
|
||
|
||
tp_sl_result = self.service.set_tp_sl(
|
||
symbol=symbol,
|
||
is_long=is_long,
|
||
size=abs(size),
|
||
tp_price=tp_price,
|
||
sl_price=sl_price
|
||
)
|
||
|
||
if tp_sl_result.get('success'):
|
||
print(f"✅ 止盈止损设置成功")
|
||
else:
|
||
print(f"❌ 止盈止损设置失败: {tp_sl_result.get('error')}")
|
||
else:
|
||
print(f"❌ 市价单失败: {result.get('error')}")
|
||
|
||
# 等待一下查看结果
|
||
print(f"\n⏳ 等待2秒查看持仓状态...")
|
||
time.sleep(2)
|
||
|
||
# 查询挂单
|
||
orders = self.service.get_open_orders(symbol)
|
||
if orders:
|
||
print(f"\n📋 当前挂单:")
|
||
for order in orders:
|
||
print(f" - ID: {order['order_id']}")
|
||
print(f" 方向: {order['side']}")
|
||
print(f" 价格: ${order['price']:,.2f}")
|
||
print(f" 数量: {order['size']}")
|
||
else:
|
||
print(f"\n📋 无挂单")
|
||
|
||
return result
|
||
|
||
def test_3_limit_order(self, symbol: str = "BTC", is_buy: bool = True, size: float = 0.001):
|
||
"""测试3:限价单(挂单测试)"""
|
||
self.print_section(f"测试3: 限价单 - {'买入' if is_buy else '卖出'} {symbol}")
|
||
|
||
# 获取当前价格
|
||
import requests
|
||
try:
|
||
response = requests.get("https://api.hyperliquid.xyz/info", json={
|
||
"type": "meta",
|
||
"coin": symbol
|
||
}, timeout=5)
|
||
data = response.json()
|
||
# 从响应中获取当前价格(简化处理,使用一个估算值)
|
||
current_price = 95000 # 假设 BTC 当前价格
|
||
except:
|
||
current_price = 95000
|
||
|
||
# 设置挂单价格(距离当前价格 1%)
|
||
if is_buy:
|
||
limit_price = current_price * 0.99 # 低于市价 1%
|
||
else:
|
||
limit_price = current_price * 1.01 # 高于市价 1%
|
||
|
||
print(f"💡 当前价格估算: ${current_price:,.2f}")
|
||
print(f"📝 挂单价格: ${limit_price:,.2f} ({'低于' if is_buy else '高于'}市价1%)")
|
||
|
||
# 下限价单
|
||
result = self.service.place_limit_order(
|
||
symbol=symbol,
|
||
is_buy=is_buy,
|
||
size=size,
|
||
price=limit_price
|
||
)
|
||
|
||
if result.get('success'):
|
||
print(f"✅ 限价单成功")
|
||
print(f" 方向: {'买入' if is_buy else '卖出'}")
|
||
print(f" 数量: {size}")
|
||
print(f" 价格: ${limit_price:,.2f}")
|
||
|
||
# 查询挂单
|
||
orders = self.service.get_open_orders(symbol)
|
||
if orders:
|
||
print(f"\n📋 当前挂单:")
|
||
for order in orders:
|
||
print(f" - ID: {order['order_id']}")
|
||
print(f" 方向: {order['side']}")
|
||
print(f" 价格: ${order['price']:,.2f}")
|
||
print(f" 数量: {order['size']}")
|
||
|
||
return result
|
||
else:
|
||
print(f"❌ 限价单失败: {result.get('error')}")
|
||
return None
|
||
|
||
def test_4_check_tp_sl(self, symbol: str = "BTC"):
|
||
"""测试4:查询止盈止损"""
|
||
self.print_section(f"测试4: 查询止盈止损 - {symbol}")
|
||
|
||
tp_sl = self.service.get_tp_sl_prices(symbol)
|
||
|
||
print(f"📊 止盈止损状态:")
|
||
if tp_sl['take_profit']:
|
||
print(f" ✅ 止盈: ${tp_sl['take_profit']:,.2f}")
|
||
else:
|
||
print(f" ➖ 止盈: 未设置")
|
||
|
||
if tp_sl['stop_loss']:
|
||
print(f" ✅ 止损: ${tp_sl['stop_loss']:,.2f}")
|
||
else:
|
||
print(f" ➖ 止损: 未设置")
|
||
|
||
return tp_sl
|
||
|
||
def test_5_cleanup(self, symbol: str = "BTC"):
|
||
"""测试5:清理(平仓、取消挂单)"""
|
||
self.print_section(f"测试5: 清理测试 - {symbol}")
|
||
|
||
# 取消所有挂单
|
||
print(f"🗑️ 取消所有挂单...")
|
||
cancel_result = self.service.cancel_all_orders(symbol)
|
||
if cancel_result.get('success'):
|
||
print(f"✅ 取消挂单成功")
|
||
else:
|
||
print(f"❌ 取消挂单失败: {cancel_result.get('error')}")
|
||
|
||
# 平仓
|
||
positions = self.service.get_open_positions()
|
||
symbol_positions = [p for p in positions if p['coin'] == symbol]
|
||
|
||
if symbol_positions:
|
||
print(f"\n📤 平仓 {symbol}...")
|
||
for pos in symbol_positions:
|
||
size = abs(pos['size'])
|
||
is_long = pos['size'] > 0
|
||
|
||
result = self.service.place_market_order(
|
||
symbol=symbol,
|
||
is_buy=not is_long, # 平仓方向相反
|
||
size=size,
|
||
reduce_only=True
|
||
)
|
||
|
||
if result.get('success'):
|
||
print(f"✅ 平仓成功: {size} {symbol}")
|
||
else:
|
||
print(f"❌ 平仓失败: {result.get('error')}")
|
||
else:
|
||
print(f"📊 无持仓需要平仓")
|
||
|
||
# 最终状态
|
||
print(f"\n📊 最终状态:")
|
||
final_positions = self.service.get_open_positions()
|
||
final_orders = self.service.get_open_orders(symbol)
|
||
|
||
print(f" 持仓: {len(final_positions)} 个")
|
||
print(f" 挂单: {len(final_orders)} 个")
|
||
|
||
if len(final_positions) == 0 and len(final_orders) == 0:
|
||
print(f"✅ 清理完成,无持仓和挂单")
|
||
else:
|
||
print(f"⚠️ 清理未完全,请检查")
|
||
|
||
def run_all_tests(self, auto_mode: bool = True):
|
||
"""运行所有测试
|
||
|
||
Args:
|
||
auto_mode: 自动模式,不等待用户确认(默认True)
|
||
"""
|
||
print("\n" + "="*60)
|
||
print(" Hyperliquid 小资金测试")
|
||
if auto_mode:
|
||
print(" 自动模式: 将直接执行所有测试")
|
||
else:
|
||
print(" 交互模式: 每步需要确认")
|
||
print("="*60)
|
||
|
||
def wait_for_confirmation(msg: str):
|
||
"""等待用户确认(仅在非自动模式下)"""
|
||
if not auto_mode:
|
||
try:
|
||
input(f"\n⚠️ {msg}\n按 Enter 继续,Ctrl+C 取消...")
|
||
except EOFError:
|
||
print("⚠️ 检测到非交互环境,切换到自动模式")
|
||
return True
|
||
return True
|
||
|
||
try:
|
||
# 测试1:账户状态
|
||
self.test_1_get_account_state()
|
||
|
||
# 测试2:市价单
|
||
wait_for_confirmation("即将测试市价单(小金额)")
|
||
self.test_2_market_order(symbol="BTC", is_buy=True, size=0.001)
|
||
|
||
# 测试3:限价单
|
||
wait_for_confirmation("即将测试限价单(小金额)")
|
||
self.test_3_limit_order(symbol="BTC", is_buy=False, size=0.001)
|
||
|
||
# 测试4:查询止盈止损
|
||
self.test_4_check_tp_sl(symbol="BTC")
|
||
|
||
# 测试5:清理
|
||
wait_for_confirmation("即将清理测试(平仓、取消挂单)")
|
||
self.test_5_cleanup(symbol="BTC")
|
||
|
||
print("\n" + "="*60)
|
||
print(" ✅ 所有测试完成")
|
||
print("="*60)
|
||
|
||
except KeyboardInterrupt:
|
||
print("\n\n⚠️ 测试被用户中断")
|
||
print("🧹 执行清理...")
|
||
|
||
# 尝试清理
|
||
self.test_5_cleanup(symbol="BTC")
|
||
|
||
except Exception as e:
|
||
logger.error(f"❌ 测试出错: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
|
||
# 尝试清理
|
||
print("\n🧹 执行清理...")
|
||
self.test_5_cleanup(symbol="BTC")
|
||
|
||
|
||
def main():
|
||
"""主函数"""
|
||
tester = HyperliquidTester()
|
||
tester.run_all_tests()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|