import time import os import asyncio import requests from datetime import datetime from flextrade.flextrade_client import Client from flextrade.constants.markets import ( BASE_MARKET_ETH_USD, BASE_MARKET_BTC_USD, BASE_MARKET_BNB_USD, BASE_MARKET_SHIB_USD, BASE_MARKET_PEPE_USD, BASE_MARKET_SUI_USD, BASE_MARKET_DOGE_USD, BASE_MARKET_AAVE_USD, BASE_MARKET_HBAR_USD, BASE_MARKET_VIRTUAL_USD, BASE_MARKET_ADA_USD, BASE_MARKET_PENDLE_USD, BASE_MARKET_TRX_USD, BASE_MARKET_AVAX_USD, BASE_MARKET_UNI_USD, BASE_MARKET_SOL_USD, BASE_MARKET_LINK_USD, BASE_MARKET_XRP_USD, BASE_MARKET_TON_USD ) from dotenv import load_dotenv load_dotenv() RPC_URL = os.getenv("RPC_URL") PRIVATE_KEY = os.getenv("PRIVATE_KEY") # List of all markets to test MARKETS = [ # BASE_MARKET_ETH_USD, # BASE_MARKET_BTC_USD, # BASE_MARKET_BNB_USD, # BASE_MARKET_SHIB_USD, # BASE_MARKET_PEPE_USD, # BASE_MARKET_SUI_USD, # BASE_MARKET_DOGE_USD, # BASE_MARKET_AAVE_USD, # BASE_MARKET_HBAR_USD, # BASE_MARKET_VIRTUAL_USD, # BASE_MARKET_ADA_USD, # BASE_MARKET_PENDLE_USD, # BASE_MARKET_TRX_USD, # BASE_MARKET_AVAX_USD, # BASE_MARKET_UNI_USD, BASE_MARKET_SOL_USD, # BASE_MARKET_LINK_USD, # BASE_MARKET_XRP_USD, # BASE_MARKET_TON_USD ] # Global variable to store latest prices with timestamps latest_prices = {} # Binance API configuration BINANCE_API_BASE_URL = "https://api.binance.com" # Mapping FlexTrade markets to Binance symbols FLEXTRADE_TO_BINANCE_MAPPING = { "ETHUSD": "ETHUSDC", "BTCUSD": "BTCUSDC", "BNBUSD": "BNBUSDC", "SOLUSD": "SOLUSDC", "DOGEUSD": "DOGEUSDC", "AAVEUSD": "AAVEUSDC", "ADAUSD": "ADAUSDC", "TRXUSD": "TRXUSDC", "AVAXUSD": "AVAXUSDC", "UNIUSD": "UNIUSDC", "LINKUSD": "LINKUSDC", "XRPUSD": "XRPUSDC" } def print_market_info(market_info, debug=False): if debug: timestamp = datetime.now().strftime("%H:%M:%S") print('[{0}] {1} : {2:.4f}'.format(timestamp, market_info["market"], market_info["price"])) def get_binance_price(symbol, debug=False): """Fetch current price from Binance API""" try: url = f"{BINANCE_API_BASE_URL}/api/v3/ticker/price" params = {"symbol": symbol} response = requests.get(url, params=params, timeout=10) response.raise_for_status() data = response.json() price = float(data["price"]) if debug: timestamp = datetime.now().strftime("%H:%M:%S") print(f'[{timestamp}] Binance {symbol}: {price:.4f}') return price except requests.exceptions.RequestException as e: if debug: print(f"❌ Binance API request error for {symbol}: {e}") return None except (KeyError, ValueError) as e: if debug: print(f"❌ Binance API data error for {symbol}: {e}") return None except Exception as e: if debug: print(f"❌ Unexpected error fetching Binance price for {symbol}: {e}") return None def get_all_binance_prices(debug=False): """Fetch prices for all mapped symbols from Binance""" binance_prices = {} if debug: print("Fetching prices from Binance API...") for flextrade_market, binance_symbol in FLEXTRADE_TO_BINANCE_MAPPING.items(): price = get_binance_price(binance_symbol, debug) if price is not None: current_timestamp = datetime.now() binance_prices[flextrade_market] = { 'price': price, 'binance_symbol': binance_symbol, 'timestamp': current_timestamp, 'timestamp_str': current_timestamp.strftime("%Y-%m-%d %H:%M:%S"), 'source': 'binance' } else: if debug: print(f"⚠️ Failed to fetch price for {flextrade_market} ({binance_symbol})") # Small delay to avoid rate limiting time.sleep(0.1) return binance_prices def compare_prices(flextrade_prices, binance_prices, debug=False): """Compare FlexTrade and Binance prices""" comparison_results = {} if debug: print("\n" + "="*80) print("PRICE COMPARISON: FlexTrade vs Binance") print("="*80) for market in flextrade_prices: if market in binance_prices: ft_price = flextrade_prices[market]['price'] bn_price = binance_prices[market]['price'] # Calculate difference price_diff = ft_price - bn_price price_diff_pct = (price_diff / bn_price) * 100 if bn_price > 0 else 0 comparison_results[market] = { 'flextrade_price': ft_price, 'binance_price': bn_price, 'difference': price_diff, 'difference_pct': price_diff_pct, 'flextrade_timestamp': flextrade_prices[market]['timestamp_str'], 'binance_timestamp': binance_prices[market]['timestamp_str'] } if debug: status = "📈" if price_diff > 0 else "📉" if price_diff < 0 else "➡️" print(f"{status} {market:<12} | FlexTrade: ${ft_price:>8.4f} | Binance: ${bn_price:>8.4f} | Diff: {price_diff:>+7.4f} ({price_diff_pct:>+6.2f}%)") elif debug: print(f"⚠️ {market:<12} | Only available on FlexTrade") # Check for Binance-only prices if debug: for market in binance_prices: if market not in flextrade_prices: bn_price = binance_prices[market]['price'] print(f"ℹ️ {market:<12} | Only available on Binance: ${bn_price:.4f}") print("="*80) return comparison_results def market_info(debug=False, include_binance=True): """Fetch market information once and update global prices""" client = Client( eth_private_key=PRIVATE_KEY, rpc_url=RPC_URL ) if debug: print("Fetching market data...\n") # Fetch FlexTrade prices for market in MARKETS: try: market_info_data = client.public.get_market_info(market) print_market_info(market_info_data, debug) # Store the latest price and timestamp in global dictionary market_name = market_info_data["market"] current_timestamp = datetime.now() latest_prices[market_name] = { 'price': market_info_data["price"], 'timestamp': current_timestamp, 'timestamp_str': current_timestamp.strftime("%Y-%m-%d %H:%M:%S"), 'source': 'flextrade' } time.sleep(15) # Wait 15 seconds between requests to avoid rate limiting except Exception as e: if debug: print(f"Error fetching market {market}: {e}") print('-' * 50) # Skip this market and continue with the next one continue # Fetch Binance prices and compare if enabled if include_binance: try: binance_prices = get_all_binance_prices(debug) # Store Binance prices in a separate section of latest_prices for market, price_data in binance_prices.items(): binance_key = f"{market}_BINANCE" latest_prices[binance_key] = price_data # Compare prices if both sources have data flextrade_only = {k: v for k, v in latest_prices.items() if not k.endswith('_BINANCE') and v.get('source') == 'flextrade'} if flextrade_only and binance_prices: comparison = compare_prices(flextrade_only, binance_prices, debug) # Store comparison results latest_prices['_comparison'] = { 'timestamp': datetime.now(), 'results': comparison } except Exception as e: if debug: print(f"❌ Error fetching Binance prices: {e}") # Continue without Binance data def market_info_loop(debug=False, include_binance=True): """Continuously fetch market information in a loop""" if debug: print("Starting market data loop - press Ctrl+C to stop") print("-" * 50) try: while True: try: market_info(debug, include_binance) # if debug: # print(f"\nSleeping for 30 seconds...\n") # time.sleep(30) # Wait 30 seconds between full cycles except Exception as e: if debug: print(f"Error in market_info cycle: {e}") print("Waiting 15 seconds before retry...") time.sleep(15) # Wait 15 seconds before retrying on error continue # except KeyboardInterrupt: # if debug: # print("\nMarket data loop stopped by user") except Exception as e: if debug: print(f"Fatal error occurred: {e}") print("Market data loop stopped") def get_latest_price(market_name): """Get the latest price for a specific market""" market_data = latest_prices.get(market_name, None) return market_data['price'] if market_data else None def get_latest_price_with_timestamp(market_name): """Get the latest price with timestamp for a specific market""" return latest_prices.get(market_name, None) def get_all_latest_prices(): """Get all latest prices with timestamps""" return latest_prices.copy() def get_all_latest_prices_only(): """Get all latest prices without timestamps (backward compatibility)""" return {market: data['price'] for market, data in latest_prices.items()} def get_binance_price_for_market(market_name): """Get the latest Binance price for a specific market""" binance_key = f"{market_name}_BINANCE" market_data = latest_prices.get(binance_key, None) return market_data['price'] if market_data else None def get_price_comparison(market_name): """Get price comparison data for a specific market""" comparison_data = latest_prices.get('_comparison', {}) results = comparison_data.get('results', {}) return results.get(market_name, None) def get_all_price_comparisons(): """Get all price comparison data""" comparison_data = latest_prices.get('_comparison', {}) return comparison_data.get('results', {}) def get_market_arbitrage_opportunities(min_percentage_diff=0.5): """Find arbitrage opportunities between FlexTrade and Binance""" comparisons = get_all_price_comparisons() opportunities = [] for market, data in comparisons.items(): abs_diff_pct = abs(data['difference_pct']) if abs_diff_pct >= min_percentage_diff: opportunity = { 'market': market, 'flextrade_price': data['flextrade_price'], 'binance_price': data['binance_price'], 'difference_pct': data['difference_pct'], 'action': 'buy_flextrade_sell_binance' if data['difference_pct'] < 0 else 'buy_binance_sell_flextrade', 'potential_profit_pct': abs_diff_pct } opportunities.append(opportunity) # Sort by potential profit percentage (highest first) opportunities.sort(key=lambda x: x['potential_profit_pct'], reverse=True) return opportunities if __name__ == '__main__': # Enable debug when running directly print("🚀 Starting market data collection with Binance price comparison...") print("📊 Number of FlexTrade markets being monitored:", len(MARKETS)) print("🔗 Binance symbols mapped:", list(FLEXTRADE_TO_BINANCE_MAPPING.values())) print("=" * 80) market_info_loop(debug=True, include_binance=True)