test bybit opening/closing orders
This commit is contained in:
348
test_bybit_eth_futures.py
Normal file
348
test_bybit_eth_futures.py
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test script for Bybit ETH futures position opening/closing
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
# Add the project root to the path
|
||||||
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
# Load environment variables from .env file
|
||||||
|
try:
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
except ImportError:
|
||||||
|
# If dotenv is not available, try to load .env manually
|
||||||
|
if os.path.exists('.env'):
|
||||||
|
with open('.env', 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
if line.strip() and not line.startswith('#'):
|
||||||
|
key, value = line.strip().split('=', 1)
|
||||||
|
os.environ[key] = value
|
||||||
|
|
||||||
|
from NN.exchanges.bybit_interface import BybitInterface
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||||
|
)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class BybitEthFuturesTest:
|
||||||
|
"""Test class for Bybit ETH futures trading"""
|
||||||
|
|
||||||
|
def __init__(self, test_mode=True):
|
||||||
|
self.test_mode = test_mode
|
||||||
|
self.bybit = BybitInterface(test_mode=test_mode)
|
||||||
|
self.test_symbol = 'ETHUSDT'
|
||||||
|
self.test_quantity = 0.01 # Small test amount
|
||||||
|
|
||||||
|
def run_tests(self):
|
||||||
|
"""Run all tests"""
|
||||||
|
print("=" * 60)
|
||||||
|
print("BYBIT ETH FUTURES POSITION TESTING")
|
||||||
|
print("=" * 60)
|
||||||
|
print(f"Test mode: {'TESTNET' if self.test_mode else 'LIVE'}")
|
||||||
|
print(f"Symbol: {self.test_symbol}")
|
||||||
|
print(f"Test quantity: {self.test_quantity} ETH")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Test 1: Connection
|
||||||
|
if not self.test_connection():
|
||||||
|
print("❌ Connection failed - stopping tests")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test 2: Check balance
|
||||||
|
if not self.test_balance():
|
||||||
|
print("❌ Balance check failed - stopping tests")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test 3: Check current positions
|
||||||
|
self.test_current_positions()
|
||||||
|
|
||||||
|
# Test 4: Get ticker
|
||||||
|
if not self.test_ticker():
|
||||||
|
print("❌ Ticker test failed - stopping tests")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test 5: Open a long position
|
||||||
|
long_order = self.test_open_long_position()
|
||||||
|
if not long_order:
|
||||||
|
print("❌ Open long position failed")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test 6: Check position after opening
|
||||||
|
time.sleep(2) # Wait for position to be reflected
|
||||||
|
if not self.test_position_after_open():
|
||||||
|
print("❌ Position check after opening failed")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test 7: Close the position
|
||||||
|
if not self.test_close_position():
|
||||||
|
print("❌ Close position failed")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test 8: Check position after closing
|
||||||
|
time.sleep(2) # Wait for position to be reflected
|
||||||
|
self.test_position_after_close()
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("✅ ALL TESTS COMPLETED SUCCESSFULLY")
|
||||||
|
print("=" * 60)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def test_connection(self):
|
||||||
|
"""Test connection to Bybit"""
|
||||||
|
print("\n📡 Testing connection to Bybit...")
|
||||||
|
|
||||||
|
# First test simple connectivity without auth
|
||||||
|
print("Testing basic API connectivity...")
|
||||||
|
try:
|
||||||
|
from NN.exchanges.bybit_rest_client import BybitRestClient
|
||||||
|
client = BybitRestClient(
|
||||||
|
api_key="dummy",
|
||||||
|
api_secret="dummy",
|
||||||
|
testnet=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test public endpoint (server time)
|
||||||
|
server_time = client.get_server_time()
|
||||||
|
print(f"✅ Public API working - Server time: {server_time.get('result', {}).get('timeSecond')}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Public API failed: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Now test with actual credentials
|
||||||
|
print("Testing with API credentials...")
|
||||||
|
try:
|
||||||
|
connected = self.bybit.connect()
|
||||||
|
if connected:
|
||||||
|
print("✅ Successfully connected to Bybit with credentials")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("❌ Failed to connect to Bybit with credentials")
|
||||||
|
print("This might be due to:")
|
||||||
|
print("- Invalid API credentials")
|
||||||
|
print("- Credentials not enabled for testnet")
|
||||||
|
print("- Missing required permissions")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Connection error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def test_balance(self):
|
||||||
|
"""Test getting account balance"""
|
||||||
|
print("\n💰 Testing account balance...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Get USDT balance (for margin)
|
||||||
|
usdt_balance = self.bybit.get_balance('USDT')
|
||||||
|
print(f"USDT Balance: {usdt_balance}")
|
||||||
|
|
||||||
|
# Get all balances
|
||||||
|
all_balances = self.bybit.get_all_balances()
|
||||||
|
print("All balances:")
|
||||||
|
for asset, balance in all_balances.items():
|
||||||
|
if balance['total'] > 0:
|
||||||
|
print(f" {asset}: Free={balance['free']}, Locked={balance['locked']}, Total={balance['total']}")
|
||||||
|
|
||||||
|
if usdt_balance > 10: # Need at least $10 for testing
|
||||||
|
print("✅ Sufficient balance for testing")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("❌ Insufficient USDT balance for testing (need at least $10)")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Balance check error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def test_current_positions(self):
|
||||||
|
"""Test getting current positions"""
|
||||||
|
print("\n📊 Checking current positions...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
positions = self.bybit.get_positions()
|
||||||
|
if positions:
|
||||||
|
print(f"Found {len(positions)} open positions:")
|
||||||
|
for pos in positions:
|
||||||
|
print(f" {pos['symbol']}: {pos['side']} {pos['size']} @ ${pos['entry_price']:.2f}")
|
||||||
|
print(f" PnL: ${pos['unrealized_pnl']:.2f} ({pos['percentage']:.2f}%)")
|
||||||
|
else:
|
||||||
|
print("No open positions found")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Position check error: {e}")
|
||||||
|
|
||||||
|
def test_ticker(self):
|
||||||
|
"""Test getting ticker information"""
|
||||||
|
print(f"\n📈 Testing ticker for {self.test_symbol}...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
ticker = self.bybit.get_ticker(self.test_symbol)
|
||||||
|
if ticker:
|
||||||
|
print(f"✅ Ticker data received:")
|
||||||
|
print(f" Last Price: ${ticker['last_price']:.2f}")
|
||||||
|
print(f" Bid: ${ticker['bid_price']:.2f}")
|
||||||
|
print(f" Ask: ${ticker['ask_price']:.2f}")
|
||||||
|
print(f" 24h Volume: {ticker['volume_24h']:.2f}")
|
||||||
|
print(f" 24h Change: {ticker['change_24h']:.4f}%")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("❌ Failed to get ticker data")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Ticker error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def test_open_long_position(self):
|
||||||
|
"""Test opening a long position"""
|
||||||
|
print(f"\n🚀 Opening long position for {self.test_quantity} {self.test_symbol}...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Place market buy order
|
||||||
|
order = self.bybit.place_order(
|
||||||
|
symbol=self.test_symbol,
|
||||||
|
side='buy',
|
||||||
|
order_type='market',
|
||||||
|
quantity=self.test_quantity
|
||||||
|
)
|
||||||
|
|
||||||
|
if 'error' in order:
|
||||||
|
print(f"❌ Order failed: {order['error']}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
print("✅ Long position opened successfully:")
|
||||||
|
print(f" Order ID: {order['order_id']}")
|
||||||
|
print(f" Symbol: {order['symbol']}")
|
||||||
|
print(f" Side: {order['side']}")
|
||||||
|
print(f" Quantity: {order['quantity']}")
|
||||||
|
print(f" Status: {order['status']}")
|
||||||
|
|
||||||
|
return order
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Open position error: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def test_position_after_open(self):
|
||||||
|
"""Test checking position after opening"""
|
||||||
|
print(f"\n📊 Checking position after opening...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
positions = self.bybit.get_positions(self.test_symbol)
|
||||||
|
if positions:
|
||||||
|
position = positions[0]
|
||||||
|
print("✅ Position found:")
|
||||||
|
print(f" Symbol: {position['symbol']}")
|
||||||
|
print(f" Side: {position['side']}")
|
||||||
|
print(f" Size: {position['size']}")
|
||||||
|
print(f" Entry Price: ${position['entry_price']:.2f}")
|
||||||
|
print(f" Mark Price: ${position['mark_price']:.2f}")
|
||||||
|
print(f" Unrealized PnL: ${position['unrealized_pnl']:.2f}")
|
||||||
|
print(f" Percentage: {position['percentage']:.2f}%")
|
||||||
|
print(f" Leverage: {position['leverage']}x")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("❌ No position found after opening")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Position check error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def test_close_position(self):
|
||||||
|
"""Test closing the position"""
|
||||||
|
print(f"\n🔄 Closing position for {self.test_symbol}...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Close the position
|
||||||
|
close_order = self.bybit.close_position(self.test_symbol)
|
||||||
|
|
||||||
|
if 'error' in close_order:
|
||||||
|
print(f"❌ Close order failed: {close_order['error']}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print("✅ Position closed successfully:")
|
||||||
|
print(f" Order ID: {close_order['order_id']}")
|
||||||
|
print(f" Symbol: {close_order['symbol']}")
|
||||||
|
print(f" Side: {close_order['side']}")
|
||||||
|
print(f" Quantity: {close_order['quantity']}")
|
||||||
|
print(f" Status: {close_order['status']}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Close position error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def test_position_after_close(self):
|
||||||
|
"""Test checking position after closing"""
|
||||||
|
print(f"\n📊 Checking position after closing...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
positions = self.bybit.get_positions(self.test_symbol)
|
||||||
|
if positions:
|
||||||
|
position = positions[0]
|
||||||
|
print("⚠️ Position still exists (may be partially closed):")
|
||||||
|
print(f" Symbol: {position['symbol']}")
|
||||||
|
print(f" Side: {position['side']}")
|
||||||
|
print(f" Size: {position['size']}")
|
||||||
|
print(f" Entry Price: ${position['entry_price']:.2f}")
|
||||||
|
print(f" Unrealized PnL: ${position['unrealized_pnl']:.2f}")
|
||||||
|
else:
|
||||||
|
print("✅ Position successfully closed - no open positions")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Position check error: {e}")
|
||||||
|
|
||||||
|
def test_order_history(self):
|
||||||
|
"""Test getting order history"""
|
||||||
|
print(f"\n📋 Checking recent orders...")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Get open orders
|
||||||
|
open_orders = self.bybit.get_open_orders(self.test_symbol)
|
||||||
|
print(f"Open orders: {len(open_orders)}")
|
||||||
|
for order in open_orders:
|
||||||
|
print(f" {order['order_id']}: {order['side']} {order['quantity']} @ ${order['price']:.2f} - {order['status']}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Order history error: {e}")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main function"""
|
||||||
|
print("Starting Bybit ETH Futures Test...")
|
||||||
|
|
||||||
|
# Check if API credentials are set
|
||||||
|
api_key = os.getenv('BYBIT_API_KEY')
|
||||||
|
api_secret = os.getenv('BYBIT_API_SECRET')
|
||||||
|
|
||||||
|
if not api_key or not api_secret:
|
||||||
|
print("❌ Please set BYBIT_API_KEY and BYBIT_API_SECRET environment variables")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Create test instance
|
||||||
|
test = BybitEthFuturesTest(test_mode=True) # Always use testnet for safety
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
success = test.run_tests()
|
||||||
|
|
||||||
|
if success:
|
||||||
|
print("\n🎉 All tests passed!")
|
||||||
|
else:
|
||||||
|
print("\n💥 Some tests failed!")
|
||||||
|
|
||||||
|
return success
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
success = main()
|
||||||
|
sys.exit(0 if success else 1)
|
249
test_bybit_eth_live.py
Normal file
249
test_bybit_eth_live.py
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test Bybit ETH futures trading with live environment
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# Add the project root to the path
|
||||||
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
# Load environment variables
|
||||||
|
try:
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
except ImportError:
|
||||||
|
if os.path.exists('.env'):
|
||||||
|
with open('.env', 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
if line.strip() and not line.startswith('#'):
|
||||||
|
key, value = line.strip().split('=', 1)
|
||||||
|
os.environ[key] = value
|
||||||
|
|
||||||
|
from NN.exchanges.bybit_interface import BybitInterface
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||||
|
)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def test_eth_futures_trading():
|
||||||
|
"""Test ETH futures trading with live environment"""
|
||||||
|
print("=" * 60)
|
||||||
|
print("BYBIT ETH FUTURES LIVE TRADING TEST")
|
||||||
|
print("=" * 60)
|
||||||
|
print("⚠️ This uses LIVE environment with real money!")
|
||||||
|
print("⚠️ Test amount: 0.001 ETH (very small)")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Check if API credentials are set
|
||||||
|
api_key = os.getenv('BYBIT_API_KEY')
|
||||||
|
api_secret = os.getenv('BYBIT_API_SECRET')
|
||||||
|
|
||||||
|
if not api_key or not api_secret:
|
||||||
|
print("❌ API credentials not found in environment")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Create Bybit interface with live environment
|
||||||
|
bybit = BybitInterface(
|
||||||
|
api_key=api_key,
|
||||||
|
api_secret=api_secret,
|
||||||
|
test_mode=False # Use live environment
|
||||||
|
)
|
||||||
|
|
||||||
|
symbol = 'ETHUSDT'
|
||||||
|
test_quantity = 0.01 # Minimum order size for ETH futures
|
||||||
|
|
||||||
|
# Test 1: Connection
|
||||||
|
print(f"\n📡 Testing connection to Bybit live environment...")
|
||||||
|
try:
|
||||||
|
if not bybit.connect():
|
||||||
|
print("❌ Failed to connect to Bybit")
|
||||||
|
return False
|
||||||
|
print("✅ Successfully connected to Bybit live environment")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Connection error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test 2: Get account balance
|
||||||
|
print(f"\n💰 Checking account balance...")
|
||||||
|
try:
|
||||||
|
usdt_balance = bybit.get_balance('USDT')
|
||||||
|
print(f"USDT Balance: ${usdt_balance:.2f}")
|
||||||
|
|
||||||
|
if usdt_balance < 5:
|
||||||
|
print("❌ Insufficient USDT balance for testing (need at least $5)")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print("✅ Sufficient balance for testing")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Balance check error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test 3: Get current ETH price
|
||||||
|
print(f"\n📈 Getting current ETH price...")
|
||||||
|
try:
|
||||||
|
ticker = bybit.get_ticker(symbol)
|
||||||
|
if not ticker:
|
||||||
|
print("❌ Failed to get ticker")
|
||||||
|
return False
|
||||||
|
|
||||||
|
current_price = ticker['last_price']
|
||||||
|
print(f"Current ETH price: ${current_price:.2f}")
|
||||||
|
print(f"Test order value: ${current_price * test_quantity:.2f}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Ticker error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test 4: Check existing positions
|
||||||
|
print(f"\n📊 Checking existing positions...")
|
||||||
|
try:
|
||||||
|
positions = bybit.get_positions(symbol)
|
||||||
|
if positions:
|
||||||
|
print(f"Found {len(positions)} existing positions:")
|
||||||
|
for pos in positions:
|
||||||
|
print(f" {pos['symbol']}: {pos['side']} {pos['size']} @ ${pos['entry_price']:.2f}")
|
||||||
|
print(f" PnL: ${pos['unrealized_pnl']:.2f}")
|
||||||
|
else:
|
||||||
|
print("No existing positions found")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Position check error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test 5: Ask user confirmation before trading
|
||||||
|
print(f"\n⚠️ TRADING CONFIRMATION")
|
||||||
|
print(f" Symbol: {symbol}")
|
||||||
|
print(f" Quantity: {test_quantity} ETH")
|
||||||
|
print(f" Estimated cost: ${current_price * test_quantity:.2f}")
|
||||||
|
print(f" Environment: LIVE (real money)")
|
||||||
|
|
||||||
|
response = input("\nDo you want to proceed with the live trading test? (y/N): ").lower()
|
||||||
|
if response != 'y' and response != 'yes':
|
||||||
|
print("❌ Trading test cancelled by user")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test 6: Open a small long position
|
||||||
|
print(f"\n🚀 Opening small long position...")
|
||||||
|
try:
|
||||||
|
order = bybit.place_order(
|
||||||
|
symbol=symbol,
|
||||||
|
side='buy',
|
||||||
|
order_type='market',
|
||||||
|
quantity=test_quantity
|
||||||
|
)
|
||||||
|
|
||||||
|
if 'error' in order:
|
||||||
|
print(f"❌ Order failed: {order['error']}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print("✅ Long position opened successfully:")
|
||||||
|
print(f" Order ID: {order['order_id']}")
|
||||||
|
print(f" Symbol: {order['symbol']}")
|
||||||
|
print(f" Side: {order['side']}")
|
||||||
|
print(f" Quantity: {order['quantity']}")
|
||||||
|
print(f" Status: {order['status']}")
|
||||||
|
|
||||||
|
order_id = order['order_id']
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Order placement error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test 7: Wait a moment and check position
|
||||||
|
print(f"\n⏳ Waiting 3 seconds for position to be reflected...")
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
try:
|
||||||
|
positions = bybit.get_positions(symbol)
|
||||||
|
if positions:
|
||||||
|
position = positions[0]
|
||||||
|
print("✅ Position confirmed:")
|
||||||
|
print(f" Symbol: {position['symbol']}")
|
||||||
|
print(f" Side: {position['side']}")
|
||||||
|
print(f" Size: {position['size']}")
|
||||||
|
print(f" Entry Price: ${position['entry_price']:.2f}")
|
||||||
|
print(f" Current PnL: ${position['unrealized_pnl']:.2f}")
|
||||||
|
print(f" Leverage: {position['leverage']}x")
|
||||||
|
else:
|
||||||
|
print("⚠️ No position found (may already be closed)")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Position check error: {e}")
|
||||||
|
|
||||||
|
# Test 8: Close the position
|
||||||
|
print(f"\n🔄 Closing the position...")
|
||||||
|
try:
|
||||||
|
close_order = bybit.close_position(symbol)
|
||||||
|
|
||||||
|
if 'error' in close_order:
|
||||||
|
print(f"❌ Close order failed: {close_order['error']}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
print("✅ Position closed successfully:")
|
||||||
|
print(f" Order ID: {close_order['order_id']}")
|
||||||
|
print(f" Symbol: {close_order['symbol']}")
|
||||||
|
print(f" Side: {close_order['side']}")
|
||||||
|
print(f" Quantity: {close_order['quantity']}")
|
||||||
|
print(f" Status: {close_order['status']}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Close position error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Test 9: Final position check
|
||||||
|
print(f"\n📊 Final position check...")
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
try:
|
||||||
|
positions = bybit.get_positions(symbol)
|
||||||
|
if positions:
|
||||||
|
position = positions[0]
|
||||||
|
print("⚠️ Position still exists:")
|
||||||
|
print(f" Size: {position['size']}")
|
||||||
|
print(f" PnL: ${position['unrealized_pnl']:.2f}")
|
||||||
|
else:
|
||||||
|
print("✅ No open positions - trading test completed successfully")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Final position check error: {e}")
|
||||||
|
|
||||||
|
# Test 10: Final balance check
|
||||||
|
print(f"\n💰 Final balance check...")
|
||||||
|
try:
|
||||||
|
final_balance = bybit.get_balance('USDT')
|
||||||
|
print(f"Final USDT Balance: ${final_balance:.2f}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Final balance check error: {e}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main function"""
|
||||||
|
print("🚀 Starting Bybit ETH Futures Live Trading Test...")
|
||||||
|
|
||||||
|
success = test_eth_futures_trading()
|
||||||
|
|
||||||
|
if success:
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("✅ BYBIT ETH FUTURES TRADING TEST COMPLETED")
|
||||||
|
print("=" * 60)
|
||||||
|
print("🎯 Your Bybit integration is fully functional!")
|
||||||
|
print("🔄 Position opening and closing works correctly")
|
||||||
|
print("💰 Account balance integration works")
|
||||||
|
print("📊 All trading functions are operational")
|
||||||
|
print("=" * 60)
|
||||||
|
else:
|
||||||
|
print("\n💥 Trading test failed!")
|
||||||
|
|
||||||
|
return success
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
success = main()
|
||||||
|
sys.exit(0 if success else 1)
|
220
test_bybit_public_api.py
Normal file
220
test_bybit_public_api.py
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Test Bybit public API functionality (no authentication required)
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# Add the project root to the path
|
||||||
|
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
from NN.exchanges.bybit_rest_client import BybitRestClient
|
||||||
|
|
||||||
|
# Configure logging
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||||
|
)
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def test_public_api():
|
||||||
|
"""Test public API endpoints"""
|
||||||
|
print("=" * 60)
|
||||||
|
print("BYBIT PUBLIC API TEST")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Test both testnet and live for public endpoints
|
||||||
|
for testnet in [True, False]:
|
||||||
|
env_name = "TESTNET" if testnet else "LIVE"
|
||||||
|
print(f"\n🔄 Testing {env_name} environment...")
|
||||||
|
|
||||||
|
client = BybitRestClient(
|
||||||
|
api_key="dummy",
|
||||||
|
api_secret="dummy",
|
||||||
|
testnet=testnet
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test 1: Server time
|
||||||
|
try:
|
||||||
|
server_time = client.get_server_time()
|
||||||
|
time_second = server_time.get('result', {}).get('timeSecond')
|
||||||
|
print(f"✅ Server time: {time_second}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Server time failed: {e}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Test 2: Get ticker for ETHUSDT
|
||||||
|
try:
|
||||||
|
ticker = client.get_ticker('ETHUSDT', 'linear')
|
||||||
|
ticker_data = ticker.get('result', {}).get('list', [])
|
||||||
|
if ticker_data:
|
||||||
|
data = ticker_data[0]
|
||||||
|
print(f"✅ ETH/USDT ticker:")
|
||||||
|
print(f" Last Price: ${float(data.get('lastPrice', 0)):.2f}")
|
||||||
|
print(f" 24h Volume: {float(data.get('volume24h', 0)):.2f}")
|
||||||
|
print(f" 24h Change: {float(data.get('price24hPcnt', 0)) * 100:.2f}%")
|
||||||
|
else:
|
||||||
|
print("❌ No ticker data received")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Ticker failed: {e}")
|
||||||
|
|
||||||
|
# Test 3: Get instruments info
|
||||||
|
try:
|
||||||
|
instruments = client.get_instruments_info('linear')
|
||||||
|
instruments_list = instruments.get('result', {}).get('list', [])
|
||||||
|
eth_instruments = [i for i in instruments_list if 'ETH' in i.get('symbol', '')]
|
||||||
|
print(f"✅ Found {len(eth_instruments)} ETH instruments")
|
||||||
|
for instr in eth_instruments[:3]: # Show first 3
|
||||||
|
print(f" {instr.get('symbol')} - Status: {instr.get('status')}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Instruments failed: {e}")
|
||||||
|
|
||||||
|
# Test 4: Get orderbook
|
||||||
|
try:
|
||||||
|
orderbook = client.get_orderbook('ETHUSDT', 'linear', 5)
|
||||||
|
ob_data = orderbook.get('result', {})
|
||||||
|
bids = ob_data.get('b', [])
|
||||||
|
asks = ob_data.get('a', [])
|
||||||
|
|
||||||
|
if bids and asks:
|
||||||
|
print(f"✅ Orderbook (top 3):")
|
||||||
|
print(f" Best bid: ${float(bids[0][0]):.2f} (qty: {float(bids[0][1]):.4f})")
|
||||||
|
print(f" Best ask: ${float(asks[0][0]):.2f} (qty: {float(asks[0][1]):.4f})")
|
||||||
|
spread = float(asks[0][0]) - float(bids[0][0])
|
||||||
|
print(f" Spread: ${spread:.2f}")
|
||||||
|
else:
|
||||||
|
print("❌ No orderbook data received")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Orderbook failed: {e}")
|
||||||
|
|
||||||
|
print(f"📊 {env_name} environment test completed")
|
||||||
|
|
||||||
|
def test_live_authentication():
|
||||||
|
"""Test live authentication (if user wants to test with live credentials)"""
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("BYBIT LIVE AUTHENTICATION TEST")
|
||||||
|
print("=" * 60)
|
||||||
|
print("⚠️ This will test with LIVE credentials (not testnet)")
|
||||||
|
|
||||||
|
# Load environment variables
|
||||||
|
try:
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
except ImportError:
|
||||||
|
# If dotenv is not available, try to load .env manually
|
||||||
|
if os.path.exists('.env'):
|
||||||
|
with open('.env', 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
if line.strip() and not line.startswith('#'):
|
||||||
|
key, value = line.strip().split('=', 1)
|
||||||
|
os.environ[key] = value
|
||||||
|
|
||||||
|
api_key = os.getenv('BYBIT_API_KEY')
|
||||||
|
api_secret = os.getenv('BYBIT_API_SECRET')
|
||||||
|
|
||||||
|
if not api_key or not api_secret:
|
||||||
|
print("❌ No API credentials found in environment")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"🔑 Using API key: {api_key[:8]}...")
|
||||||
|
|
||||||
|
# Test with live environment (testnet=False)
|
||||||
|
client = BybitRestClient(
|
||||||
|
api_key=api_key,
|
||||||
|
api_secret=api_secret,
|
||||||
|
testnet=False # Use live environment
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test connectivity
|
||||||
|
try:
|
||||||
|
if client.test_connectivity():
|
||||||
|
print("✅ Basic connectivity OK")
|
||||||
|
else:
|
||||||
|
print("❌ Basic connectivity failed")
|
||||||
|
return
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Connectivity error: {e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Test authentication
|
||||||
|
try:
|
||||||
|
if client.test_authentication():
|
||||||
|
print("✅ Authentication successful!")
|
||||||
|
|
||||||
|
# Get account info
|
||||||
|
account_info = client.get_account_info()
|
||||||
|
accounts = account_info.get('result', {}).get('list', [])
|
||||||
|
|
||||||
|
if accounts:
|
||||||
|
print("📊 Account information:")
|
||||||
|
for account in accounts:
|
||||||
|
account_type = account.get('accountType', 'Unknown')
|
||||||
|
print(f" Account Type: {account_type}")
|
||||||
|
|
||||||
|
coins = account.get('coin', [])
|
||||||
|
usdt_balance = None
|
||||||
|
for coin in coins:
|
||||||
|
if coin.get('coin') == 'USDT':
|
||||||
|
usdt_balance = float(coin.get('walletBalance', 0))
|
||||||
|
break
|
||||||
|
|
||||||
|
if usdt_balance:
|
||||||
|
print(f" USDT Balance: ${usdt_balance:.2f}")
|
||||||
|
|
||||||
|
# Show positions if any
|
||||||
|
try:
|
||||||
|
positions = client.get_positions('linear')
|
||||||
|
pos_list = positions.get('result', {}).get('list', [])
|
||||||
|
active_positions = [p for p in pos_list if float(p.get('size', 0)) != 0]
|
||||||
|
|
||||||
|
if active_positions:
|
||||||
|
print(f" Active Positions: {len(active_positions)}")
|
||||||
|
for pos in active_positions:
|
||||||
|
symbol = pos.get('symbol')
|
||||||
|
side = pos.get('side')
|
||||||
|
size = float(pos.get('size', 0))
|
||||||
|
pnl = float(pos.get('unrealisedPnl', 0))
|
||||||
|
print(f" {symbol}: {side} {size} (PnL: ${pnl:.2f})")
|
||||||
|
else:
|
||||||
|
print(" No active positions")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ⚠️ Could not get positions: {e}")
|
||||||
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print("❌ Authentication failed")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Authentication error: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main function"""
|
||||||
|
print("🚀 Starting Bybit API Tests...")
|
||||||
|
|
||||||
|
# Test public API
|
||||||
|
test_public_api()
|
||||||
|
|
||||||
|
# Ask user if they want to test live authentication
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
response = input("Do you want to test live authentication? (y/N): ").lower()
|
||||||
|
|
||||||
|
if response == 'y' or response == 'yes':
|
||||||
|
success = test_live_authentication()
|
||||||
|
if success:
|
||||||
|
print("\n✅ Live authentication test passed!")
|
||||||
|
print("🎯 Your Bybit integration is working!")
|
||||||
|
else:
|
||||||
|
print("\n❌ Live authentication test failed")
|
||||||
|
else:
|
||||||
|
print("\n📋 Skipping live authentication test")
|
||||||
|
|
||||||
|
print("\n🎉 Public API tests completed successfully!")
|
||||||
|
print("📈 Bybit integration is functional for market data")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Reference in New Issue
Block a user