Files
hedge/app.py

768 lines
33 KiB
Python
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import time
import threading
import json
import os
from datetime import datetime
from market import (
market_info_loop,
get_latest_price,
get_all_latest_prices,
get_latest_price_with_timestamp,
get_binance_price_for_market,
get_price_comparison,
get_market_arbitrage_opportunities
)
from order import create_market_order, create_trigger_order, update_trigger_order, cancel_trigger_order, list_trigger_orders
from position import list_open_positions
from flextrade.constants.markets import BASE_MARKET_ETH_USD, BASE_MARKET_SOL_USD, BASE_MARKET_BTC_USD
from flextrade.enum import Action
# Validate Action enum is properly imported
print(f"✅ Action enum imported: BUY={Action.BUY} (boolean), SELL={Action.SELL} (boolean)")
# Configuration
ENABLE_AUTO_HEDGE = True # Set to True to enable automatic hedging
ENABLE_TRIGGER_ORDERS = True # Set to True to enable trigger order functionality
ORDER_TRACKING_FILE = "opened_trigger_orders.json" # File to store all opened trigger orders
# Single coin configuration
MONITORED_COIN = "SOL" # Change this to monitor different coins: SOL, ETH, BTC, etc.
MONITORED_MARKET_NAME = "SOLUSD" # Market name for price lookup
MONITORED_MARKET_CONSTANT = BASE_MARKET_SOL_USD # Market constant for orders
SUB_ACCOUNT_ID = 1 # Example sub-account ID for testing
HEDGE_PRICE_THRESHOLD = 167.75 # Price threshold for auto-hedging
HEDGE_SIZE = 500.0 # Size of the hedge order
HEDGE_PRICE_SL = 1.0 # Stop-loss threshold for hedging
# Global storage for active orders
active_orders = {
"trigger_orders": [], # List of {order_id, market, account_id, action, size, trigger_price}
"market_orders": [] # List of market order transactions
}
# Track executed hedges to prevent duplicates
executed_hedges = {
"hedge_executed": False,
"last_hedge_price": 0,
"initial_position_check_done": False
}
def save_last_trigger_order_id(order_id, account_id, market, action, size, trigger_price):
"""
Save a new trigger order to the opened orders JSON file
Args:
order_id (int): Order ID
account_id (int): Account ID
market (str): Market constant
action (Action): Buy/Sell action
size (float): Order size
trigger_price (float): Trigger price
"""
try:
# Load existing orders
existing_orders = load_opened_trigger_orders_data()
if existing_orders is None:
existing_orders = {"opened_orders": []}
# Create new order data
new_order = {
"order_id": order_id,
"account_id": account_id,
"market": str(market),
"action": safe_action_to_string(action),
"size": size,
"trigger_price": trigger_price,
"created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"coin": MONITORED_COIN
}
# Check if order already exists (prevent duplicates)
existing_order_ids = [order.get("order_id") for order in existing_orders.get("opened_orders", [])]
if order_id not in existing_order_ids:
existing_orders["opened_orders"].append(new_order)
# Save updated orders list
with open(ORDER_TRACKING_FILE, 'w') as f:
json.dump(existing_orders, f, indent=2)
print(f"💾 Added trigger order ID {order_id} to {ORDER_TRACKING_FILE}")
print(f" Total opened orders: {len(existing_orders['opened_orders'])}")
else:
print(f" Order ID {order_id} already exists in {ORDER_TRACKING_FILE}")
except Exception as e:
print(f"❌ Error saving trigger order ID: {e}")
def load_opened_trigger_orders_data():
"""
Load all opened trigger orders from JSON file
Returns:
dict: Orders data or None if file doesn't exist or error
"""
try:
if not os.path.exists(ORDER_TRACKING_FILE):
print(f" No existing order tracking file found: {ORDER_TRACKING_FILE}")
return None
with open(ORDER_TRACKING_FILE, 'r') as f:
orders_data = json.load(f)
return orders_data
except Exception as e:
print(f"❌ Error loading trigger orders: {e}")
return None
def load_last_trigger_order_id():
"""
Load and display all opened trigger orders from JSON file
Returns:
dict: Orders data or None if file doesn't exist or error
"""
try:
orders_data = load_opened_trigger_orders_data()
if not orders_data:
return None
opened_orders = orders_data.get("opened_orders", [])
print(f"📂 Loaded opened trigger orders from {ORDER_TRACKING_FILE}:")
print(f" Total active orders: {len(opened_orders)}")
if opened_orders:
print(" Order details:")
for i, order in enumerate(opened_orders, 1):
print(f" {i}. ✅ Order ID: {order.get('order_id', 'N/A')}")
print(f" Account: {order.get('account_id', 'N/A')} | Market: {order.get('market', 'N/A')}")
print(f" Action: {order.get('action', 'N/A')} | Size: {order.get('size', 'N/A')}")
print(f" Trigger Price: ${order.get('trigger_price', 0):.2f}")
print(f" Created: {order.get('created_at', 'N/A')} | Coin: {order.get('coin', 'N/A')}")
if i < len(opened_orders): # Don't add extra line after last order
print()
return orders_data
except Exception as e:
print(f"❌ Error loading trigger orders: {e}")
return None
def clear_last_trigger_order_file():
"""
Clear the opened trigger orders tracking file
"""
try:
if os.path.exists(ORDER_TRACKING_FILE):
os.remove(ORDER_TRACKING_FILE)
print(f"🗑️ Cleared order tracking file: {ORDER_TRACKING_FILE}")
else:
print(f" Order tracking file doesn't exist: {ORDER_TRACKING_FILE}")
except Exception as e:
print(f"❌ Error clearing order tracking file: {e}")
def mark_order_as_cancelled(order_id):
"""
Remove a cancelled order from the tracking file
Args:
order_id (int): Order ID to remove
"""
try:
orders_data = load_opened_trigger_orders_data()
if not orders_data:
print(f" No orders data found to update")
return False
opened_orders = orders_data.get("opened_orders", [])
original_count = len(opened_orders)
# Remove the order with the matching order_id
updated_orders = [order for order in opened_orders if order.get("order_id") != order_id]
if len(updated_orders) < original_count:
# Order was found and removed
orders_data["opened_orders"] = updated_orders
# Save updated orders list
with open(ORDER_TRACKING_FILE, 'w') as f:
json.dump(orders_data, f, indent=2)
print(f"✅ Removed cancelled order ID {order_id} from {ORDER_TRACKING_FILE}")
print(f" Remaining orders: {len(updated_orders)}")
return True
else:
print(f"⚠️ Order ID {order_id} not found in tracking file")
return False
except Exception as e:
print(f"❌ Error removing cancelled order: {e}")
return False
def get_active_orders_from_file():
"""
Get list of active orders from the tracking file
Returns:
list: List of active orders
"""
try:
orders_data = load_opened_trigger_orders_data()
if not orders_data:
return []
# All orders in the file are active since cancelled ones are removed
opened_orders = orders_data.get("opened_orders", [])
return opened_orders
except Exception as e:
print(f"❌ Error getting active orders: {e}")
return []
def check_existing_positions_for_hedges():
"""
Check existing open positions and mark appropriate hedges as executed
to prevent duplicate hedge orders for the monitored coin.
Also closes all existing trigger orders and creates new stop-loss orders for hedged positions.
"""
try:
print(f"🔍 Checking existing positions for {MONITORED_COIN} hedge requirements...")
# First, close all existing trigger orders (if method is available)
print("🧹 Attempting to close existing trigger orders...")
# Load active trigger orders from file
active_orders_in_file = get_active_orders_from_file()
if active_orders_in_file:
print(f"🗑️ Found {len(active_orders_in_file)} active trigger orders to cancel...")
else:
print(" No active trigger orders found in file.")
for account_id in [SUB_ACCOUNT_ID]:
# Cancel each active trigger order found in the file
for order in active_orders_in_file:
order_id = order.get("order_id")
print(f"🗑️ Attempting to cancel trigger order ID: {order_id}")
try:
cancel_result = handle_cancel_trigger_order(account_id, MONITORED_MARKET_CONSTANT, order_id)
if cancel_result:
print(f"✅ Successfully cancelled order {order_id}")
# Remove from file after successful cancellation
mark_order_as_cancelled(order_id)
else:
print(f"❌ Failed to cancel order {order_id}")
except Exception as e:
print(f"⚠️ Error cancelling trigger order {order_id}: {e}")
time.sleep(8) # Delay between cancellations
print("⏳ Brief wait before position check...")
time.sleep(3)
# Now check positions for hedge requirements
hedge_positions_found = []
for account_id in [SUB_ACCOUNT_ID]:
positions = list_open_positions(account_id, delay=2)
if positions:
print(f"📊 Found {len(positions)} open position(s) in account {account_id}")
for position in positions:
market = position.get("market", "")
size = position.get("position_size", 0)
entry_price = position.get("avg_entry_price", 0)
orderIndex = position.get("orderIndex", 0)
direction = "LONG" if size > 0 else "SHORT"
print(f" - {market} ({direction}): Size={size:.4f}, Entry=${entry_price:.2f}, orderIndex={orderIndex}")
# Check hedge requirements for monitored coin
if MONITORED_MARKET_NAME in market and size > 0 and entry_price > HEDGE_PRICE_THRESHOLD:
print(f"{MONITORED_COIN} hedge requirement met: Position size {size:.4f} at ${entry_price:.2f} (above ${HEDGE_PRICE_THRESHOLD})")
executed_hedges["hedge_executed"] = True
executed_hedges["last_hedge_price"] = entry_price
# Store hedge position info for stop-loss creation
hedge_positions_found.append({
'account_id': account_id,
'size': size,
'entry_price': entry_price
})
# Add delay between account checks to avoid rate limiting
time.sleep(3)
# Create stop-loss trigger orders for hedged positions
if hedge_positions_found:
print(f"\n🛡️ Creating stop-loss orders for {len(hedge_positions_found)} hedged position(s)...")
for hedge_pos in hedge_positions_found:
account_id = hedge_pos['account_id']
size = hedge_pos['size']
entry_price = hedge_pos['entry_price']
# Calculate stop-loss price: entry_price - HEDGE_PRICE_SL
stop_loss_price = entry_price - HEDGE_PRICE_SL
print(f"📉 Creating stop-loss order for position:")
print(f" Account: {account_id}, Size: {size:.4f}")
print(f" Entry Price: ${entry_price:.2f}")
print(f" Stop-Loss Price: ${stop_loss_price:.2f} (Entry - ${HEDGE_PRICE_SL})")
print(f" orderIndex: {hedge_pos.get('orderIndex', 'N/A')}")
# Retry logic for creating stop-loss trigger order
max_retries = 3
retry_delay = 5
trigger_result = None
for attempt in range(max_retries):
try:
print(f"🔄 Attempt {attempt + 1}/{max_retries} to create stop-loss order...")
# Create stop-loss trigger order (SELL when price goes below stop-loss price)
trigger_result = handle_trigger_order(
account_id=account_id,
market=MONITORED_MARKET_CONSTANT,
action=Action.SELL,
size=size,
trigger_price=stop_loss_price,
trigger_above=False # Trigger when price goes BELOW stop-loss price
)
if trigger_result:
print(f"✅ Stop-loss trigger order created successfully!")
break
else:
print(f"❌ Failed to create stop-loss trigger order (attempt {attempt + 1})")
except Exception as e:
print(f"❌ Exception during stop-loss creation (attempt {attempt + 1}): {e}")
# Wait before retry if not the last attempt
if attempt < max_retries - 1:
wait_time = retry_delay * (attempt + 1)
print(f"⏳ Waiting {wait_time} seconds before retry...")
time.sleep(wait_time)
if not trigger_result:
print(f"❌ Failed to create stop-loss trigger order after {max_retries} attempts")
# Add longer delay between different positions
time.sleep(5)
executed_hedges["initial_position_check_done"] = True
print("✅ Initial position check completed")
# Show current hedge status
print(f"\n📋 {MONITORED_COIN} Hedge Status Summary:")
print(f" {MONITORED_COIN} Hedge: {'✅ Executed' if executed_hedges['hedge_executed'] else '❌ Not executed'}")
if executed_hedges["hedge_executed"]:
print(f" Last Hedge Price: ${executed_hedges['last_hedge_price']:.2f}")
print(f" Stop-Loss Orders: {'✅ Created' if hedge_positions_found else '❌ None needed'}")
print()
except Exception as e:
print(f"❌ Error checking existing positions: {e}")
executed_hedges["initial_position_check_done"] = True # Mark as done even on error to prevent infinite retries
def start_market_data_thread(debug=True, include_binance=True):
"""Start market data collection in a separate thread"""
market_thread = threading.Thread(target=lambda: market_info_loop(debug, include_binance), daemon=True)
market_thread.start()
return market_thread
def store_trigger_order(result, market, account_id, action, size, trigger_price):
"""Store trigger order information for later management"""
if result and 'order' in result and 'orderIndex' in result['order']:
order_id = result['order']['orderIndex']
order_info = {
'order_id': order_id,
'market': market,
'account_id': account_id,
'action': action,
'size': size,
'trigger_price': trigger_price,
'tx_hash': result['tx'].hex(),
'created_at': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
active_orders["trigger_orders"].append(order_info)
print(f"📝 Stored trigger order info: ID {order_id}")
# Save to file for persistence
save_last_trigger_order_id(order_id, account_id, market, action, size, trigger_price)
return order_info
return None
def get_active_trigger_orders():
"""Get list of all active trigger orders"""
return active_orders["trigger_orders"].copy()
def remove_trigger_order(order_id):
"""Remove a trigger order from active list and remove from file"""
active_orders["trigger_orders"] = [
order for order in active_orders["trigger_orders"]
if order['order_id'] != order_id
]
print(f"📝 Removed trigger order ID {order_id} from active list")
# Also remove from the persistent file
mark_order_as_cancelled(order_id)
def safe_action_to_string(action):
"""Convert action to string safely, handling both enum and boolean cases"""
if hasattr(action, 'name'):
return action.name
elif action is True or action == 1:
return "BUY"
elif action is False or action == 0:
return "SELL"
else:
return str(action)
def handle_market_order(account_id, market, action, size):
"""
Handle market order creation with error handling
Args:
account_id (int): Account ID to trade with
market (str): Market constant (e.g., BASE_MARKET_ETH_USD)
action (Action): Action.BUY or Action.SELL
size (float): Order size
"""
try:
print(f"\n--- Creating Market Order ---")
# Convert action to string safely
action_name = safe_action_to_string(action)
print(f"Account: {account_id}, Market: {market}, Action: {action_name}, Size: {size}")
result = create_market_order(account_id, market, action, size)
if result:
print(f"✅ Market order successful!")
print(f"Transaction: {result['tx'].hex()}")
else:
print("❌ Market order failed!")
print("--- Order Complete ---\n")
return result
except Exception as e:
print(f"❌ Error handling market order: {e}")
return None
def handle_trigger_order(account_id, market, action, size, trigger_price, trigger_above=True):
"""
Handle trigger order creation with error handling
Args:
account_id (int): Account ID to trade with
market (str): Market constant (e.g., BASE_MARKET_ETH_USD)
action (Action): Action.BUY or Action.SELL
size (float): Order size
trigger_price (float): Price at which the order should trigger
trigger_above (bool): True to trigger when price goes above, False for below
"""
try:
print(f"\n--- Creating Trigger Order ---")
# Convert action to string safely
action_name = safe_action_to_string(action)
trigger_direction = "above" if trigger_above else "below"
print(f"Account: {account_id}, Market: {market}, Action: {action_name}, Size: {size}")
print(f"Trigger: {trigger_direction} ${trigger_price:.2f}")
result = create_trigger_order(account_id, market, action, size, trigger_price, trigger_above)
if result:
print(f"✅ Trigger order successful!")
print(f"Transaction: {result['tx'].hex()}")
print(f"Order ID: {result['order']['orderIndex']}")
# Store the order for later management
store_trigger_order(result, market, account_id, action, size, trigger_price)
else:
print("❌ Trigger order failed!")
print("--- Order Complete ---\n")
return result
except Exception as e:
print(f"❌ Error handling trigger order: {e}")
return None
def handle_update_trigger_order(account_id, order_id, action, size, trigger_price, trigger_above=True):
"""
Handle trigger order update with error handling
Args:
account_id (int): Account ID
order_id (int): Order ID to update
action (Action): Action.BUY or Action.SELL
size (float): New order size
trigger_price (float): New trigger price
trigger_above (bool): True to trigger when price goes above, False for below
"""
try:
print(f"\n--- Updating Trigger Order ---")
trigger_direction = "above" if trigger_above else "below"
action_name = safe_action_to_string(action)
print(f"Order ID: {order_id}, Action: {action_name}, Size: {size}")
print(f"New trigger: {trigger_direction} ${trigger_price:.2f}")
result = update_trigger_order(account_id, order_id, action, size, trigger_price, trigger_above)
if result:
print(f"✅ Trigger order updated successfully!")
print(f"Transaction: {result['tx'].hex()}")
else:
print("❌ Trigger order update failed!")
print("--- Update Complete ---\n")
return result
except Exception as e:
print(f"❌ Error updating trigger order: {e}")
return None
def handle_cancel_trigger_order(account_id, market, order_id):
"""
Handle trigger order cancellation with error handling
Args:
account_id (int): Account ID
market (str): Market constant
order_id (int): Order ID to cancel
"""
try:
print(f"\n--- Cancelling Trigger Order ---")
print(f"Order ID: {order_id}, Market: {market}")
result = cancel_trigger_order(account_id, market, order_id)
if result:
print(f"✅ Trigger order cancelled successfully!")
print(f"Transaction: {result['tx'].hex()}")
# Remove from active orders list
remove_trigger_order(order_id)
else:
print("❌ Trigger order cancellation failed!")
print("--- Cancellation Complete ---\n")
return result
except Exception as e:
print(f"❌ Error cancelling trigger order: {e}")
return None
def smart_market_order(market_name, market_constant, action, size, price_threshold=None):
"""
Create a market order with optional price threshold checking
Args:
market_name (str): Market name for price lookup (e.g., "ETHUSD")
market_constant (str): Market constant for order (e.g., BASE_MARKET_ETH_USD)
action (Action): Action.BUY or Action.SELL
size (float): Order size
price_threshold (float): Optional price threshold for conditional orders
Returns:
dict: Order result or None if conditions not met
"""
current_price_data = get_latest_price_with_timestamp(market_name)
if not current_price_data:
print(f"❌ No price data available for {market_name}")
return None
current_price = current_price_data['price']
print(f"📊 Current {market_name} price: ${current_price:.2f}")
# Check price threshold if provided
if price_threshold:
if action == Action.BUY and current_price > price_threshold:
print(f"⏸️ Price ${current_price:.2f} above buy threshold ${price_threshold:.2f} - order not placed")
return None
elif action == Action.SELL and current_price < price_threshold:
print(f"⏸️ Price ${current_price:.2f} below sell threshold ${price_threshold:.2f} - order not placed")
return None
print(f"✅ Price conditions met, placing order...")
return handle_market_order(SUB_ACCOUNT_ID, market_constant, action, size)
def smart_trigger_order(market_name, market_constant, action, size, trigger_price, trigger_above=True, offset_percentage=None):
"""
Create a trigger order with smart pricing based on current market conditions
Args:
market_name (str): Market name for price lookup (e.g., "ETHUSD")
market_constant (str): Market constant for order (e.g., BASE_MARKET_ETH_USD)
action (Action): Action.BUY or Action.SELL
size (float): Order size
trigger_price (float): Price at which the order should trigger
trigger_above (bool): True to trigger when price goes above, False for below
offset_percentage (float): Optional percentage offset from current price for automatic trigger calculation
Returns:
dict: Order result or None if conditions not met
"""
current_price_data = get_latest_price_with_timestamp(market_name)
if not current_price_data:
print(f"❌ No price data available for {market_name}")
return None
current_price = current_price_data['price']
print(f"📊 Current {market_name} price: ${current_price:.2f}")
# Calculate trigger price based on offset if provided
if offset_percentage:
if trigger_above:
calculated_trigger = current_price * (1 + offset_percentage / 100)
else:
calculated_trigger = current_price * (1 - offset_percentage / 100)
print(f"🧮 Calculated trigger price: ${calculated_trigger:.2f} ({offset_percentage:+.1f}% from current)")
trigger_price = calculated_trigger
# Validate trigger price makes sense
trigger_direction = "above" if trigger_above else "below"
if trigger_above and trigger_price <= current_price:
print(f"⚠️ Warning: Trigger price ${trigger_price:.2f} is not above current price ${current_price:.2f}")
elif not trigger_above and trigger_price >= current_price:
print(f"⚠️ Warning: Trigger price ${trigger_price:.2f} is not below current price ${current_price:.2f}")
print(f"✅ Creating trigger order: {trigger_direction} ${trigger_price:.2f}")
return handle_trigger_order(SUB_ACCOUNT_ID, market_constant, action, size, trigger_price, trigger_above)
def main():
print(f"Starting app - monitoring {MONITORED_COIN} with market data collection...")
print(f"Monitored Coin: {MONITORED_COIN}")
print(f"Market: {MONITORED_MARKET_NAME}")
print(f"Hedge Price Threshold: ${HEDGE_PRICE_THRESHOLD}")
print(f"Auto-hedge enabled: {ENABLE_AUTO_HEDGE}")
print("-" * 50)
# Load last trigger order information on startup
print("🔍 Checking for existing opened trigger orders...")
orders_data = load_last_trigger_order_id()
if orders_data:
total_count = len(orders_data.get("opened_orders", []))
print(f"✅ Found {total_count} active trigger orders for {MONITORED_COIN} coin")
else:
print(" No existing opened trigger orders found")
print()
# Start market data collection in background thread with Binance comparison
start_market_data_thread(debug=False, include_binance=True)
# Give some time for initial market data to be collected
time.sleep(10)
try:
while True:
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(f"[{current_time}] update!")
# Show some sample prices with timestamps (FlexTrade and Binance)
monitored_data = get_latest_price_with_timestamp(MONITORED_MARKET_NAME)
# Check if we have received first successful price update and haven't checked positions yet
if (not executed_hedges["initial_position_check_done"] and monitored_data):
print(f"\n🎯 First successful price update received for {MONITORED_COIN} - checking existing positions...")
check_existing_positions_for_hedges()
# Get Binance prices for comparison
monitored_binance = get_latest_price_with_timestamp(f"{MONITORED_MARKET_NAME}_BINANCE")
if monitored_data or monitored_binance:
ft_price = f"${monitored_data['price']:.2f}" if monitored_data else "N/A"
bn_price = f"${monitored_binance['price']:.2f}" if monitored_binance else "N/A"
ft_time = monitored_data['timestamp_str'] if monitored_data else "N/A"
bn_time = monitored_binance['timestamp_str'] if monitored_binance else "N/A"
print(f"{MONITORED_COIN}/USD: FlexTrade={ft_price} ({ft_time}) | Binance={bn_price} ({bn_time})")
# Show price difference if both available
if monitored_data and monitored_binance:
price_diff = monitored_data['price'] - monitored_binance['price']
diff_pct = (price_diff / monitored_binance['price']) * 100 if monitored_binance['price'] > 0 else 0
diff_emoji = "📈" if price_diff > 0 else "📉" if price_diff < 0 else "➡️"
print(f"{MONITORED_COIN} Difference: {diff_emoji} {price_diff:+.4f} ({diff_pct:+.2f}%)")
# Show total number of markets with prices
all_prices = get_all_latest_prices()
flextrade_markets = len([k for k in all_prices.keys() if not k.endswith('_BINANCE') and k != '_comparison'])
binance_markets = len([k for k in all_prices.keys() if k.endswith('_BINANCE')])
print(f"Total markets tracked: FlexTrade={flextrade_markets}, Binance={binance_markets}")
# Show arbitrage opportunities if available
try:
arbitrage_ops = get_market_arbitrage_opportunities(min_percentage_diff=0.5)
if arbitrage_ops:
print(f"\n🎯 Found {len(arbitrage_ops)} arbitrage opportunities (>0.5% difference):")
for i, op in enumerate(arbitrage_ops[:3]): # Show top 3
action_emoji = "📈" if "buy_flextrade" in op['action'] else "📉"
print(f" {i+1}. {action_emoji} {op['market']}: {op['potential_profit_pct']:.2f}% potential profit")
print(f" FlexTrade: ${op['flextrade_price']:.4f} | Binance: ${op['binance_price']:.4f}")
print(f" Strategy: {op['action'].replace('_', ' ').title()}")
else:
print("🎯 No significant arbitrage opportunities found (threshold: 0.5%)")
# Show smaller differences for informational purposes
small_ops = get_market_arbitrage_opportunities(min_percentage_diff=0.1)
if small_ops:
best_small = small_ops[0] # Show best small opportunity
diff_emoji = "📈" if best_small['difference_pct'] > 0 else "📉"
print(f" Best small difference: {diff_emoji} {best_small['market']} ({best_small['potential_profit_pct']:.2f}%)")
except Exception as e:
print(f"⚠️ Error checking arbitrage opportunities: {e}")
print() # Extra line for readability
# Auto-hedging logic
if ENABLE_AUTO_HEDGE:
# Hedging logic with duplicate prevention for monitored coin
if (monitored_data and monitored_data['price'] > HEDGE_PRICE_THRESHOLD and
not executed_hedges["hedge_executed"]): # Only execute once
print(f"🤖 Auto-hedge triggered: {MONITORED_COIN} price above ${HEDGE_PRICE_THRESHOLD}")
# Execute market order to buy the monitored coin
market_result = smart_market_order(MONITORED_MARKET_NAME, MONITORED_MARKET_CONSTANT, Action.BUY, 100.0)
if market_result:
print(f"🤖 Auto-hedge triggered: {MONITORED_COIN} stop-loss trigger")
time.sleep(10)
# Create stop-loss trigger order
trigger_result = smart_trigger_order(MONITORED_MARKET_NAME, MONITORED_MARKET_CONSTANT, Action.SELL, 100.0, 0, trigger_above=False, offset_percentage=5)
if trigger_result:
# Mark hedge as executed
executed_hedges["hedge_executed"] = True
executed_hedges["last_hedge_price"] = monitored_data['price']
print(f"{MONITORED_COIN} hedge completed at price ${monitored_data['price']:.2f}")
# Reset hedge flag if price drops significantly below hedge price
if (monitored_data and monitored_data['price'] < (HEDGE_PRICE_THRESHOLD * 0.95) and
executed_hedges["hedge_executed"]):
print(f"🔄 Resetting {MONITORED_COIN} hedge flag - price dropped to ${monitored_data['price']:.2f}")
executed_hedges["hedge_executed"] = False
# Sleep for 60 seconds (1 minute)
time.sleep(60)
except Exception as e:
print(f"An error occurred: {e}")
if __name__ == "__main__":
main()