import time from datetime import datetime import threading 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 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 = False # Set to True to enable automatic hedging ENABLE_TRIGGER_ORDERS = False # Set to True to enable trigger order functionality sol_hedge_price = 161 # Example price for SOL auto-hedging SUB_ACCOUNT_ID = 1 # Example sub-account ID for testing # 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 = { "sol_hedge_executed": False, "last_hedge_price": 0 } 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_info = { 'order_id': result['order']['orderIndex'], '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_info['order_id']}") 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""" 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") 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("Starting app with market data collection...") print("-" * 40) # 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) eth_data = get_latest_price_with_timestamp("ETHUSD") btc_data = get_latest_price_with_timestamp("BTCUSD") sol_data = get_latest_price_with_timestamp("SOLUSD") # Get Binance prices for comparison eth_binance = get_latest_price_with_timestamp("ETHUSD_BINANCE") btc_binance = get_latest_price_with_timestamp("BTCUSD_BINANCE") sol_binance = get_latest_price_with_timestamp("SOLUSD_BINANCE") if eth_data or eth_binance: ft_price = f"${eth_data['price']:.2f}" if eth_data else "N/A" bn_price = f"${eth_binance['price']:.2f}" if eth_binance else "N/A" print(f"ETH/USD: FlexTrade={ft_price} | Binance={bn_price}") if btc_data or btc_binance: ft_price = f"${btc_data['price']:.2f}" if btc_data else "N/A" bn_price = f"${btc_binance['price']:.2f}" if btc_binance else "N/A" print(f"BTC/USD: FlexTrade={ft_price} | Binance={bn_price}") if sol_data or sol_binance: ft_price = f"${sol_data['price']:.2f}" if sol_data else "N/A" bn_price = f"${sol_binance['price']:.2f}" if sol_binance else "N/A" ft_time = sol_data['timestamp_str'] if sol_data else "N/A" bn_time = sol_binance['timestamp_str'] if sol_binance else "N/A" print(f"SOL/USD: FlexTrade={ft_price} ({ft_time}) | Binance={bn_price} ({bn_time})") # Show price difference if both available if sol_data and sol_binance: price_diff = sol_data['price'] - sol_binance['price'] diff_pct = (price_diff / sol_binance['price']) * 100 if sol_binance['price'] > 0 else 0 diff_emoji = "šŸ“ˆ" if price_diff > 0 else "šŸ“‰" if price_diff < 0 else "āž”ļø" print(f"SOL 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: # Market order examples - immediate execution # if eth_data and eth_data['price'] < 3000: # Buy ETH if price drops below $3000 # print("šŸ¤– Auto-hedge triggered: ETH price below $3000") # smart_market_order("ETHUSD", BASE_MARKET_ETH_USD, Action.BUY, 0.01) # SOL hedging logic with duplicate prevention if (sol_data and sol_data['price'] > sol_hedge_price and not executed_hedges["sol_hedge_executed"]): # Only execute once print(f"šŸ¤– Auto-hedge triggered: SOL price above ${sol_hedge_price}") # Execute market order to buy SOL market_result = smart_market_order("SOLUSD", BASE_MARKET_SOL_USD, Action.BUY, 100.0) if market_result: print("šŸ¤– Auto-hedge triggered: SOL stop-loss trigger") time.sleep(10) # Create stop-loss trigger order trigger_result = smart_trigger_order("SOLUSD", BASE_MARKET_SOL_USD, Action.SELL, 100.0, 0, trigger_above=False, offset_percentage=5) if trigger_result: # Mark hedge as executed executed_hedges["sol_hedge_executed"] = True executed_hedges["last_hedge_price"] = sol_data['price'] print(f"āœ… SOL hedge completed at price ${sol_data['price']:.2f}") # Reset hedge flag if price drops significantly below hedge price if (sol_data and sol_data['price'] < (sol_hedge_price * 0.95) and executed_hedges["sol_hedge_executed"]): print(f"šŸ”„ Resetting SOL hedge flag - price dropped to ${sol_data['price']:.2f}") executed_hedges["sol_hedge_executed"] = False # Trigger order examples - conditional execution # Create stop-loss orders: # if eth_data and eth_data['price'] > 3500: # Set stop-loss 5% below current ETH price # print("šŸ¤– Setting ETH stop-loss trigger") # smart_trigger_order("ETHUSD", BASE_MARKET_ETH_USD, Action.SELL, 0.01, 0, trigger_above=False, offset_percentage=5) # Create take-profit orders: # if btc_data and btc_data['price'] < 50000: # Set take-profit 10% above current BTC price # print("šŸ¤– Setting BTC take-profit trigger") # smart_trigger_order("BTCUSD", BASE_MARKET_BTC_USD, Action.SELL, 0.001, 0, trigger_above=True, offset_percentage=10) # Sleep for 60 seconds (1 minute) time.sleep(60) except Exception as e: print(f"An error occurred: {e}") if __name__ == "__main__": main()