revert broken changes - indentations
This commit is contained in:
@ -276,7 +276,7 @@ class TradingExecutor:
|
||||
quote_asset = 'USDC' # Use USDC instead
|
||||
logger.info(f"BALANCE CHECK: Using USDC fallback balance for {symbol}")
|
||||
else:
|
||||
available_balance = self.exchange.get_balance(quote_asset)
|
||||
available_balance = self.exchange.get_balance(quote_asset)
|
||||
|
||||
logger.info(f"BALANCE CHECK: Symbol: {symbol}, Action: {action}, Required: ${required_capital:.2f} {quote_asset}, Available: ${available_balance:.2f} {quote_asset}")
|
||||
|
||||
@ -303,23 +303,23 @@ class TradingExecutor:
|
||||
logger.info(f"LOCK ACQUIRED: Executing {action} for {symbol}")
|
||||
start_time = time.time()
|
||||
|
||||
if action == 'BUY':
|
||||
if action == 'BUY':
|
||||
result = self._execute_buy(symbol, confidence, current_price)
|
||||
elif action == 'SELL':
|
||||
elif action == 'SELL':
|
||||
result = self._execute_sell(symbol, confidence, current_price)
|
||||
elif action == 'SHORT': # Explicitly handle SHORT if it's a direct signal
|
||||
elif action == 'SHORT': # Explicitly handle SHORT if it's a direct signal
|
||||
result = self._execute_short(symbol, confidence, current_price)
|
||||
else:
|
||||
logger.warning(f"Unknown action: {action}")
|
||||
else:
|
||||
logger.warning(f"Unknown action: {action}")
|
||||
result = False
|
||||
|
||||
execution_time = time.time() - start_time
|
||||
logger.info(f"EXECUTION COMPLETE: {action} for {symbol} took {execution_time:.2f}s, result: {result}")
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error executing {action} signal for {symbol}: {e}")
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"Error executing {action} signal for {symbol}: {e}")
|
||||
return False
|
||||
finally:
|
||||
self.lock.release()
|
||||
logger.debug(f"LOCK RELEASED: {action} for {symbol}")
|
||||
@ -386,7 +386,7 @@ class TradingExecutor:
|
||||
logger.info(f"Test mode: bypassing trade interval for {symbol}")
|
||||
else:
|
||||
logger.info(f"Trade interval not met for {symbol} ({time_since_last:.1f}s < {min_interval}s)")
|
||||
return False
|
||||
return False
|
||||
|
||||
# Check concurrent positions
|
||||
max_positions = self.exchange_config.get('max_concurrent_positions',
|
||||
@ -442,7 +442,7 @@ class TradingExecutor:
|
||||
# Only create position if order was actually filled
|
||||
if result.get('filled', True): # Assume filled for backward compatibility
|
||||
self.positions[symbol] = Position(
|
||||
symbol=symbol,
|
||||
symbol=symbol,
|
||||
side='LONG',
|
||||
quantity=float(filled_quantity),
|
||||
entry_price=float(fill_price),
|
||||
@ -452,7 +452,7 @@ class TradingExecutor:
|
||||
logger.info(f"BUY position created: {filled_quantity:.6f} {symbol} at ${fill_price:.4f}")
|
||||
self.last_trade_time[symbol] = datetime.now()
|
||||
return True
|
||||
else:
|
||||
else:
|
||||
logger.error(f"BUY order placed but not filled: {result}")
|
||||
return False
|
||||
else:
|
||||
@ -488,12 +488,12 @@ class TradingExecutor:
|
||||
|
||||
if self.simulation_mode:
|
||||
# Create simulated short position
|
||||
self.positions[symbol] = Position(
|
||||
symbol=symbol,
|
||||
self.positions[symbol] = Position(
|
||||
symbol=symbol,
|
||||
side='SHORT',
|
||||
quantity=quantity,
|
||||
entry_price=current_price,
|
||||
entry_time=datetime.now(),
|
||||
quantity=quantity,
|
||||
entry_price=current_price,
|
||||
entry_time=datetime.now(),
|
||||
order_id=f"sim_{int(datetime.now().timestamp())}"
|
||||
)
|
||||
logger.info(f"Simulated SHORT order: {quantity:.6f} {symbol} at ${current_price:.2f}")
|
||||
@ -517,9 +517,9 @@ class TradingExecutor:
|
||||
order_id=result['orderId']
|
||||
)
|
||||
logger.info(f"SHORT position created: {filled_quantity:.6f} {symbol} at ${fill_price:.4f}")
|
||||
self.last_trade_time[symbol] = datetime.now()
|
||||
return True
|
||||
else:
|
||||
self.last_trade_time[symbol] = datetime.now()
|
||||
return True
|
||||
else:
|
||||
logger.error(f"SHORT order placed but not filled: {result}")
|
||||
return False
|
||||
else:
|
||||
@ -628,7 +628,7 @@ class TradingExecutor:
|
||||
try:
|
||||
self.exchange.cancel_order(symbol, order_id)
|
||||
logger.info(f"Cancelled unfilled order {order_id}")
|
||||
except Exception as e:
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to cancel unfilled order {order_id}: {e}")
|
||||
|
||||
# If this was the last attempt, return failure
|
||||
@ -1190,10 +1190,10 @@ class TradingExecutor:
|
||||
raw_balances = self.exchange.get_all_balances()
|
||||
if raw_balances:
|
||||
# Convert to the expected format with 'type' field
|
||||
combined_balances = {}
|
||||
combined_balances = {}
|
||||
for asset, balance_data in raw_balances.items():
|
||||
if isinstance(balance_data, dict):
|
||||
combined_balances[asset] = {
|
||||
combined_balances[asset] = {
|
||||
'free': balance_data.get('free', 0.0),
|
||||
'locked': balance_data.get('locked', 0.0),
|
||||
'total': balance_data.get('total', 0.0),
|
||||
@ -1201,7 +1201,7 @@ class TradingExecutor:
|
||||
}
|
||||
|
||||
logger.info(f"Retrieved balances for {len(combined_balances)} assets from {self.primary_name}")
|
||||
return combined_balances
|
||||
return combined_balances
|
||||
else:
|
||||
logger.warning(f"No balances returned from {self.primary_name} exchange")
|
||||
return {}
|
||||
|
304
test_bybit_eth_futures_fixed.py
Normal file
304
test_bybit_eth_futures_fixed.py
Normal file
@ -0,0 +1,304 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Fixed Bybit ETH futures trading test with proper minimum order size handling
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import logging
|
||||
import json
|
||||
|
||||
# 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 get_instrument_info(bybit: BybitInterface, symbol: str) -> dict:
|
||||
"""Get instrument information including minimum order size"""
|
||||
try:
|
||||
instruments = bybit.get_instruments("linear")
|
||||
for instrument in instruments:
|
||||
if instrument.get('symbol') == symbol:
|
||||
return instrument
|
||||
return {}
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting instrument info: {e}")
|
||||
return {}
|
||||
|
||||
def test_eth_futures_trading():
|
||||
"""Test ETH futures trading with proper minimum order size"""
|
||||
print("🚀 Starting Fixed Bybit ETH Futures Live Trading Test...")
|
||||
print("=" * 60)
|
||||
print("BYBIT ETH FUTURES LIVE TRADING TEST (FIXED)")
|
||||
print("=" * 60)
|
||||
print("⚠️ This uses LIVE environment with real money!")
|
||||
print("⚠️ Will check minimum order size first")
|
||||
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 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 instrument information to check minimum order size
|
||||
print(f"\n📋 Getting instrument information for {symbol}...")
|
||||
try:
|
||||
instrument_info = get_instrument_info(bybit, symbol)
|
||||
if not instrument_info:
|
||||
print(f"❌ Failed to get instrument info for {symbol}")
|
||||
return False
|
||||
|
||||
print("✅ Instrument information retrieved:")
|
||||
print(f" Symbol: {instrument_info.get('symbol')}")
|
||||
print(f" Status: {instrument_info.get('status')}")
|
||||
print(f" Base Coin: {instrument_info.get('baseCoin')}")
|
||||
print(f" Quote Coin: {instrument_info.get('quoteCoin')}")
|
||||
|
||||
# Extract minimum order size
|
||||
lot_size_filter = instrument_info.get('lotSizeFilter', {})
|
||||
min_order_qty = float(lot_size_filter.get('minOrderQty', 0.01))
|
||||
max_order_qty = float(lot_size_filter.get('maxOrderQty', 10000))
|
||||
qty_step = float(lot_size_filter.get('qtyStep', 0.01))
|
||||
|
||||
print(f" Minimum Order Qty: {min_order_qty}")
|
||||
print(f" Maximum Order Qty: {max_order_qty}")
|
||||
print(f" Quantity Step: {qty_step}")
|
||||
|
||||
# Use minimum order size for testing
|
||||
test_quantity = min_order_qty
|
||||
print(f" Using test quantity: {test_quantity} ETH")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Instrument info error: {e}")
|
||||
return False
|
||||
|
||||
# Test 3: Get account balance
|
||||
print(f"\n💰 Checking account balance...")
|
||||
try:
|
||||
usdt_balance = bybit.get_balance('USDT')
|
||||
print(f"USDT Balance: ${usdt_balance:.2f}")
|
||||
|
||||
# Calculate required balance (with some buffer)
|
||||
current_price_data = bybit.get_ticker(symbol)
|
||||
if not current_price_data:
|
||||
print("❌ Failed to get current ETH price")
|
||||
return False
|
||||
|
||||
current_price = current_price_data['last_price']
|
||||
required_balance = current_price * test_quantity * 1.1 # 10% buffer
|
||||
|
||||
print(f"Current ETH price: ${current_price:.2f}")
|
||||
print(f"Required balance: ${required_balance:.2f}")
|
||||
|
||||
if usdt_balance < required_balance:
|
||||
print(f"❌ Insufficient USDT balance for testing (need at least ${required_balance:.2f})")
|
||||
return False
|
||||
|
||||
print("✅ Sufficient balance for testing")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Balance check 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)")
|
||||
print(f" Minimum order size confirmed: {min_order_qty}")
|
||||
|
||||
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 5 seconds for position to be reflected...")
|
||||
time.sleep(5)
|
||||
|
||||
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']}")
|
||||
# Don't return False here, as the position might still exist
|
||||
print("⚠️ You may need to manually close the position")
|
||||
else:
|
||||
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}")
|
||||
print("⚠️ You may need to manually close the position")
|
||||
|
||||
# Test 9: Final position check
|
||||
print(f"\n📊 Final position check...")
|
||||
time.sleep(3)
|
||||
|
||||
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}")
|
||||
print("💡 You may want to manually close this position")
|
||||
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}")
|
||||
|
||||
balance_change = final_balance - usdt_balance
|
||||
if balance_change > 0:
|
||||
print(f"💰 Profit: +${balance_change:.2f}")
|
||||
elif balance_change < 0:
|
||||
print(f"📉 Loss: ${balance_change:.2f}")
|
||||
else:
|
||||
print(f"🔄 No change: ${balance_change:.2f}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Final balance check error: {e}")
|
||||
|
||||
return True
|
||||
|
||||
def main():
|
||||
"""Main function"""
|
||||
print("🚀 Starting Fixed 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("📏 Minimum order size handling works")
|
||||
print("=" * 60)
|
||||
else:
|
||||
print("\n💥 Trading test failed!")
|
||||
print("🔍 Check the error messages above for details")
|
||||
|
||||
return success
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = main()
|
||||
sys.exit(0 if success else 1)
|
@ -3495,7 +3495,7 @@ class CleanTradingDashboard:
|
||||
# Train CNN model with multiple passes for enhanced learning
|
||||
if hasattr(self.orchestrator.cnn_model, 'train_on_batch'):
|
||||
for _ in range(int(training_weight)):
|
||||
loss = self.orchestrator.cnn_model.train_on_batch(feature_tensor, target_tensor)
|
||||
loss = self.orchestrator.cnn_model.train_on_batch(feature_tensor, target_tensor)
|
||||
logger.info(f"CNN enhanced training on executed signal - loss: {loss:.4f}, pnl: {pnl:.2f}")
|
||||
|
||||
except Exception as e:
|
||||
|
Reference in New Issue
Block a user